A synchronized instance method locks this (the whole call is the critical section); a synchronized block locks whatever object reference you name in the parentheses, and can cover just the lines that need protection. Both end up doing monitorenter/monitorexit — the only question is which object's monitor.
Equivalence
A synchronized instance method is exactly sugar for a block over this:
public synchronized void m() { // locks 'this'
body();
}
// is equivalent to:
public void m() {
synchronized (this) { // same monitor
body();
}
}
For a static method the implicit lock is the Class object instead (ClassName.class).
Why blocks are usually better
Two reasons interviewers want to hear:
- Narrower scope = less contention. A method holds the lock for its entire body, including slow work that doesn't touch shared state. A block locks only the few lines that do.
- You control the lock object. Synchronizing on
thisleaks your lock: any outside code holding a reference to your object cansynchronized (yourObject)and interfere, or accidentally deadlock with you. A private lock object is encapsulated and safe.
class SafeCounter {
private final Object lock = new Object(); // private, dedicated monitor
private int count;
public void increment() {
prepare(); // not synchronized - no shared state
synchronized (lock) { // minimal critical section
count++;
}
}
}
The trick
Different objects mean no mutual exclusion. Two threads calling a synchronized method on two different instances never block each other — each locks its own this. That is correct for per-instance state but wrong if the state is shared (e.g. a static field).