synchronized Keyword
Intermediatesynchronized provides mutual exclusion using intrinsic locks — preventing race conditions on shared mutable state.
Overview
synchronized is Java's built-in mechanism for mutual exclusion and memory visibility. Every object has an intrinsic lock (monitor). A synchronized method or block acquires this lock; other threads trying to acquire the same lock block until it is released. synchronized also establishes a happens-before relationship — changes made in a synchronized block are visible to threads that subsequently acquire the same lock.
Synchronized Methods and Blocks
synchronized on an instance method locks on this. On a static method, it locks on the Class object. A synchronized block lets you specify any object as the lock — often a private final lock object.
Using a private lock object is better than locking on this because external code cannot accidentally acquire the same lock.
public class SafeCounter {
private int count = 0;
private final Object lock = new Object(); // dedicated lock
// Synchronized method — locks on 'this'
public synchronized void increment() {
count++;
}
// Synchronized block — locks on dedicated lock object
public void decrement() {
synchronized (lock) {
count--;
}
}
// Static synchronized — locks on SafeCounter.class
private static int instances = 0;
public static synchronized void registerInstance() {
instances++;
}
public synchronized int get() { return count; }
}
// Now race-condition-free
SafeCounter counter = new SafeCounter();
List<Thread> threads = IntStream.range(0, 1000)
.mapToObj(i -> new Thread(counter::increment))
.collect(Collectors.toList());
threads.forEach(Thread::start);
for (Thread t : threads) t.join();
System.out.println(counter.get()); // Always 1000wait(), notify(), notifyAll()
wait() releases the lock and suspends the current thread until another thread calls notify() or notifyAll() on the same object. These methods must be called inside a synchronized block.
Always call wait() in a loop (not an if) to guard against spurious wakeups and to re-check the condition after being woken.
public class BoundedBuffer<T> {
private final Queue<T> queue = new LinkedList<>();
private final int capacity;
public BoundedBuffer(int capacity) {
this.capacity = capacity;
}
public synchronized void put(T item) throws InterruptedException {
while (queue.size() == capacity) { // loop — not if
wait(); // release lock, suspend
}
queue.add(item);
notifyAll(); // wake up waiting consumers
}
public synchronized T take() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
T item = queue.poll();
notifyAll(); // wake up waiting producers
return item;
}
}Deadlock and How to Avoid It
A deadlock occurs when two or more threads wait for each other's locks indefinitely. Classic scenario: Thread A holds lock1, waits for lock2. Thread B holds lock2, waits for lock1.
Prevention strategies: always acquire locks in the same global order; use tryLock() with timeout (ReentrantLock); minimise lock scope; prefer higher-level concurrency utilities.
// DEADLOCK — acquiring locks in different orders
Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock1) {
Thread.sleep(50);
synchronized (lock2) { /* ... */ } // waits for lock2
}
});
Thread t2 = new Thread(() -> {
synchronized (lock2) {
Thread.sleep(50);
synchronized (lock1) { /* ... */ } // waits for lock1
}
});
// t1 and t2 will deadlock
// FIX — always acquire locks in the same order
Thread t1Fixed = new Thread(() -> {
synchronized (lock1) { // lock1 first
synchronized (lock2) { /* ... */ }
}
});
Thread t2Fixed = new Thread(() -> {
synchronized (lock1) { // lock1 first (same order)
synchronized (lock2) { /* ... */ }
}
});Interactive Visualization
Key Points to Remember
- synchronized on instance method locks on this; on static method locks on Class.
- Use a private final lock object instead of this for better encapsulation.
- synchronized provides both mutual exclusion and memory visibility (happens-before).
- Always call wait() in a loop to guard against spurious wakeups.
- Deadlock prevention: acquire locks in a consistent global order, or use tryLock().
Practice synchronized Keyword in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is the difference between a synchronized method and a synchronized block?
What is a deadlock and how do you prevent it?
Why should wait() always be called in a loop?
What is the difference between notify() and notifyAll()?
What is an intrinsic lock (monitor) in Java?
Ask Aria about synchronized Keyword
Your personal AI tutor — ask anything about this concept