Java Intrinsic Locks and Monitor Semantics

Java intrinsic locks provide mutual exclusion through an object’s monitor and are used by `synchronized` methods and blocks. They ensure that only one thread at a time can execute a synchronized region protected by the same monitor.

Every Java object can be associated with a monitor, which provides the locking mechanism used by `synchronized`. When a thread enters a synchronized block or method, it must acquire the relevant object’s monitor before executing the protected code.

A synchronized instance method locks on the current object, `this`. A synchronized static method instead locks on the `Class` object representing that class. A synchronized block lets you explicitly choose the object used as the lock, such as `synchronized (lock) { ... }`.

If one thread already owns a monitor, another thread attempting to acquire that same monitor must wait until the owner releases it. The same thread can acquire an intrinsic lock it already owns again; this reentrant behavior allows nested synchronized calls using the same monitor.

Intrinsic locking also establishes memory-visibility guarantees. An unlock of a monitor happens-before a subsequent successful lock of that same monitor, so properly synchronized threads can observe writes made before the unlock. Synchronization therefore addresses both mutual exclusion and visibility, not just preventing simultaneous execution.

Key points

Interview questions

What is an intrinsic lock in Java?

An intrinsic lock is the monitor associated with a Java object and used by `synchronized`. A thread must acquire the relevant monitor before entering a synchronized region protected by that object. If another thread already owns it, the attempting thread waits. The lock is reentrant, so the owning thread can acquire it again.

What does a synchronized instance method lock on?

A synchronized instance method locks on the current object, which is `this`. Therefore, two threads calling synchronized instance methods on the same object contend for the same monitor. Calls on different object instances normally use different monitors and can proceed independently. This is different from a static synchronized method, which locks the class object.

Why are intrinsic locks called reentrant?

A lock is reentrant because a thread that already owns a monitor can acquire that same monitor again without blocking itself. The runtime tracks the ownership and nested acquisition count. The monitor is not fully released until the corresponding nested exits have occurred. This makes nested synchronized calls using the same object possible.

Does `synchronized` provide memory visibility as well as mutual exclusion?

Yes. Monitor synchronization provides a happens-before relationship between an unlock of a monitor and a subsequent successful lock of that same monitor. This means writes performed before the unlock can become visible to the thread that later acquires the monitor. Therefore, `synchronized` is both a coordination mechanism and a memory-visibility mechanism.