Unravel โบ Java concepts โบ Concurrency
synchronized and locks
synchronized lets only one thread at a time run a block of code on a given lock object, protecting shared data from interleaved access.
Learn these first
At a glance
A single-key bathroom: whoever holds the key goes in, everyone else waits outside.
- 1synchronized (lock) { ..} takes the lock on lock, runs the block, and releases it on exit, even if an exception is thrown. A synchronized method locks this (or the class for static methods).
- 2Two threads using different lock objects do not exclude each other, so every access to the same data must use the same lock
- 3The lock also makes changes visible: what one thread wrote before releasing is seen by the next thread that acquires the same lock
- 4wait/notify let threads pause until a condition changes; they must be called while holding the lock and inside a loop that rechecks the condition
- Keep synchronized blocks small: holding a lock while doing I/O blocks everyone
- Each object has a monitor in its header
public class Counter { private int count; private final Object lock = new Object(); public void increment() { synchronized (lock) { count++; } } public int get() { synchronized (lock) { return count; } }}Read the full explanation (about 1 min)
synchronized lets only one thread at a time run a block of code on a given lock object, protecting shared data from interleaved access.
A mental model
A single-key bathroom: whoever holds the key goes in, everyone else waits outside. Everyone must agree on which key guards which room.
How it works
synchronized (lock) { ... } takes the lock on lock, runs the block, and releases it on exit, even if an exception is thrown. A synchronized method locks this (or the class for static methods).
Two threads using different lock objects do not exclude each other, so every access to the same data must use the same lock.
The lock also makes changes visible: what one thread wrote before releasing is seen by the next thread that acquires the same lock.
wait/notify let threads pause until a condition changes; they must be called while holding the lock and inside a loop that rechecks the condition.
Going deeper
Keep synchronized blocks small: holding a lock while doing I/O blocks everyone. Taking two locks in different orders in different places causes deadlock; always acquire them in a consistent order. Do not lock on a string literal, a boxed Integer or a publicly reachable object, since unrelated code may lock the same instance.
Under the hood
Each object has a monitor in its header. Uncontended locking is cheap; contended locking inflates the monitor and may park threads in the OS. Since JDK 21 a virtual thread blocked inside synchronized could pin its carrier thread (improved in later releases).
Common mistakes
- Different locks for the same data.
- Locking on a public or shared object like a String.
- Long operations inside the lock.
- Inconsistent lock ordering (deadlock).
waitwithout a condition loop.
How Unravel recognises it
When you paste code, Unravel looks for these signs of synchronized and locks. Spotting them yourself is a good habit when you read unfamiliar code:
- Annotations:
@GuardedBy - Method calls:
wait()notify()notifyAll() - Language constructs:
synchronized
Part of a learning path
- Concurrency fundamentals ยท previous: Threads and shared state ยท next: volatile and atomic classes
Related concepts
Builds on this
Frequently asked questions
What is synchronized and locks?
synchronized lets only one thread at a time run a block of code on a given lock object, protecting shared data from interleaved access.
What are the most common mistakes with synchronized and locks?
Different locks for the same data. Locking on a public or shared object like a String. Long operations inside the lock. Inconsistent lock ordering (deadlock). wait without a condition loop.
How can I see synchronized and locks in real code?
Paste your own Java into Unravel and it will point out where synchronized and locks appears, explain how it works at the detail level you choose, and draw the flow of the code around it.