If synchronized is the syntax, the monitor is the underlying coordination mechanism.
You do not need JVM implementation internals to use Java concurrency well. But you do need a correct conceptual model of what the monitor is doing for you.
Problem Statement
When you write:
synchronized (lock) {
// critical section
}
What actually happens conceptually?
If you cannot answer that, it becomes harder to reason about:
- lock ownership
- waiting threads
waitandnotify- contention
That is why the monitor concept matters.
Correct Mental Model
In Java, every object can act as a monitor.
A monitor conceptually provides:
- exclusive ownership by one thread at a time
- a place where other threads wait to enter
- a condition-waiting mechanism used by
wait,notify, andnotifyAll
When a thread enters a synchronized section on an object:
- it tries to acquire that object’s monitor
When it exits:
- it releases the monitor
This is why synchronized is often called intrinsic locking:
the lock is built into the object model conceptually.
Why This Matters
If multiple threads synchronize on the same object, they coordinate through the same monitor.
If they synchronize on different objects, they do not.
That sounds obvious, but it explains many real bugs:
- writer synchronizes on one lock
- reader synchronizes on another
- both assume the state is protected
- it is not
The monitor model helps you see why.
Runnable Example
import java.util.concurrent.TimeUnit;
public class MonitorDemo {
private static final Object LOCK = new Object();
public static void main(String[] args) throws Exception {
Thread first = new Thread(() -> runTask("first"), "first-thread");
Thread second = new Thread(() -> runTask("second"), "second-thread");
first.start();
second.start();
first.join();
second.join();
}
static void runTask(String name) {
synchronized (LOCK) {
System.out.println(name + " entered critical section on " + Thread.currentThread().getName());
sleep(800);
System.out.println(name + " leaving critical section on " + Thread.currentThread().getName());
}
}
static void sleep(long millis) {
try {
TimeUnit.MILLISECONDS.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
}
What this shows:
- both threads target the same monitor object
- one thread owns the monitor at a time
- the other must wait
That is the monitor doing its job.
Intrinsic Locking vs Explicit Locking
Intrinsic locking means:
- monitor ownership is tied to the object used in
synchronized
Explicit locking means:
- a lock object such as
ReentrantLockmanages the ownership explicitly through APIs
For now, the important part is: monitor-based locking is the default built-in coordination model of Java objects.
Later posts compare it with explicit locks.
Production-Style Example
Suppose an in-memory inventory object protects these fields:
- available
- reserved
- sold
If every update synchronizes on the same Inventory instance or same dedicated lock object, one monitor governs the invariant.
If one code path synchronizes on this and another on a separate lock field, protection is fractured.
That means:
- the code may look “locked”
- but the state is still effectively unprotected
The monitor model reveals why.
wait and notify Depend on Monitor Ownership
wait, notify, and notifyAll operate on the monitor too.
That is why Java requires them to be called only while holding the relevant monitor.
This later becomes critical when we discuss:
- guarded blocks
- producer-consumer designs
- missed notifications
Without the monitor concept, those APIs feel arbitrary. With it, the rules are coherent.
Failure Modes
Common mistakes:
- synchronizing on public objects that outside code may also lock
- using different monitor objects for related shared state
- calling
wait/notifywithout really understanding the monitor involved
If a design cannot clearly state “this monitor protects this state,” it is too vague.
Testing and Debugging Notes
Review questions:
- what object is the monitor?
- which state does that monitor protect?
- do all relevant code paths use the same monitor?
These questions are simple, but they expose many locking flaws.
Thread dumps also become easier to read once you understand that BLOCKED often means a thread is waiting to enter a monitor owned elsewhere.
Decision Guide
Use one monitor per protected invariant boundary.
Do not rely on broad accidental locking. Make the protected state and its monitor relationship obvious.
That clarity matters more than cleverness.
Key Takeaways
- a monitor is the conceptual synchronization mechanism behind
synchronized - one thread owns a monitor at a time
wait,notify, andnotifyAlldepend on monitor ownership- monitor clarity is essential for correct intrinsic locking design