Detailed explanation
Synchronized methods and synchronized blocks use Java’s intrinsic monitor mechanism to provide mutual exclusion and memory visibility. Their main differences are which object supplies the monitor and how much code executes while holding it. An instance synchronized method acquires the monitor of this; a static synchronized method acquires the monitor of the declaring class’s Class object, such as Counter.class. A synchronized block explicitly selects its monitor using synchronized (lockObject) { ... }. Threads exclude one another only when they acquire the same monitor, so instance and static synchronized methods do not automatically block each other.
A synchronized method holds its monitor throughout the method body. A block can protect only the operations that must execute atomically, leaving unrelated computation, logging or expensive I/O outside. This can reduce contention, but moving work outside is safe only when it does not depend on protected state remaining unchanged. For example, checking a shared balance and deducting money must stay within one critical section. Blocks also support private final Object locks, preventing external callers from directly acquiring an internal monitor as they could with this.
Both forms are reentrant: a thread already holding a monitor can acquire it again. Both release the monitor on normal completion or when an exception exits the protected region. Under the Java Memory Model, unlocking a monitor happens-before a subsequent lock of that same monitor, making earlier writes visible to the acquiring thread. Under the hood, synchronized methods carry the ACC_SYNCHRONIZED bytecode flag, while blocks use monitorenter and monitorexit instructions, with exception handling ensuring release.
The crucial interview detail is consistent locking. In the supplied Counter example, incrementMethod protects count using this, whereas incrementBlock uses lock; concurrent calls can therefore lose updates. Both paths, and relevant reads, must follow one synchronization policy. Separate locks suit independent state, not invariants spanning both fields. Avoid string literals, boxed values and reassignable lock references. Blocks offer flexibility, but methods remain clear when the entire operation needs one monitor; advanced requirements such as timed acquisition call for explicit concurrency utilities.
Key points to remember
- Instance synchronized methods lock this; static synchronized methods lock the declaring class’s Class object.
- Synchronized blocks choose an explicit monitor and can narrow the critical section.
- Both forms provide reentrancy, automatic release on exit and identical same-monitor visibility guarantees.
- All accesses participating in a shared-state invariant must follow a consistent synchronization policy.
- Methods use ACC_SYNCHRONIZED; blocks use monitorenter and monitorexit bytecode instructions.
Common mistakes candidates make
- Assuming different locks protect the same field: the supplied Counter methods use different monitors and are not mutually exclusive.
- Moving state-dependent validation outside the lock, separating a check from the update it must protect.
- Locking on string literals, boxed values or reassignable references, creating unintended sharing or inconsistent monitor selection.
Likely follow-up questions
Is a synchronized instance method equivalent to a synchronized block on this?
For mutual exclusion and visibility, wrapping the entire method body in synchronized (this) provides equivalent monitor protection. The bytecode representation differs, and a smaller block changes how long the monitor is held.
Are synchronized blocks always faster than synchronized methods?
No; both use the same intrinsic locking mechanism. A block can improve concurrency by reducing unnecessary time under the lock, but performance depends on contention, workload and JVM optimisations.
When should you use ReentrantLock instead?
Use ReentrantLock when you need features such as tryLock, timed or interruptible acquisition, configurable fairness or multiple Condition objects. Unlike synchronized, it requires explicit unlocking, normally in a finally block.
Interview tip: Start with “same mechanism, different monitor selection and scope,” then demonstrate why protecting one field with two different locks is unsafe.
