HuntExams Academy logo
JavaAdvanced#concurrency

Difference between synchronized and volatile?

Answer

synchronized provides mutual exclusion and visibility for blocks/methods. volatile guarantees visibility (reads see the latest write) but not atomicity. Use volatile for simple flags, synchronized or Locks for compound actions.

Example

private volatile boolean running = true; // visibility only
public synchronized void increment() { count++; } // mutual exclusion + visibility

Detailed explanation

In Java, synchronized and volatile both provide memory-visibility guarantees, but they solve different concurrency problems. synchronized provides mutual exclusion: only one thread at a time can execute code protected by the same monitor. It also ensures visibility between threads acquiring and releasing that monitor. volatile applies to a field and makes reads and writes participate in the Java Memory Model’s visibility and ordering rules, without making threads acquire a monitor. Choose based on whether you need to publish a value or protect an operation involving shared state.

Under the hood, every Java object has an associated monitor. A synchronized instance method locks this; a static synchronized method locks the class’s Class object; a synchronized block locks the specified object. Unlocking a monitor happens-before a subsequent successful lock of that same monitor, so earlier writes become visible to the acquiring thread. Consequently, public synchronized void increment() { count++; } safely protects the read-modify-write sequence only when all competing accesses follow a compatible locking discipline. Synchronization is reentrant: a thread can acquire a monitor it already holds.

A write to a volatile field happens-before subsequent reads of that field. For example, private volatile boolean running = true; lets a worker repeatedly checking running observe another thread’s update to false. The guarantee also publishes writes performed before the volatile write to a thread performing a corresponding subsequent volatile read. This is a memory-model guarantee, not a promise that every access physically goes to main memory. Individual volatile reads and writes are atomic, including long and double, but compound operations such as count++ or if (!initialized) initialize() are not made atomic.

Interviewers expect you to distinguish visibility, atomicity, and mutual exclusion rather than simply call one option faster. Use volatile for independent flags or safely publishing a reference when no compound invariant needs protection; a volatile reference does not make its object’s fields thread-safe. Use synchronized or an explicit lock for coordinated updates, and consider AtomicInteger for atomic counters. Monitor contention can block threads; volatile access does not acquire a monitor, but it still has ordering costs.

Key points to remember

  • synchronized provides mutual exclusion and visibility through the same monitor.
  • volatile provides visibility and ordering without mutual exclusion.
  • Volatile reads and writes are atomic; compound actions such as count++ are not.
  • Instance synchronized methods lock this; static synchronized methods lock the Class object.
  • Use volatile for independent flags, locks for compound invariants, and atomic classes for suitable single-variable updates.

Common mistakes candidates make

  • Assuming volatile int count makes count++ thread-safe.
  • Synchronizing writes while leaving reads unprotected, or using different monitors for the same shared state.
  • Claiming volatile makes referenced objects thread-safe or guarantees a particular physical memory-access mechanism.

Likely follow-up questions

Why is count++ unsafe when count is volatile?

It performs a read, an addition, and a write as separate steps. Two threads can read the same value and overwrite each other’s updates; use synchronized or AtomicInteger.incrementAndGet().

Does a field need to be volatile if every access is synchronized?

No, provided every access uses the same monitor. That monitor supplies both the necessary visibility and mutual exclusion.

How does synchronized differ from ReentrantLock?

Both provide reentrant mutual exclusion and memory-visibility guarantees. ReentrantLock additionally supports features such as timed or interruptible acquisition, but requires explicit unlocking, normally in a finally block.

Interview tip: Start with visibility versus mutual exclusion, then contrast a volatile stop flag with a synchronized counter increment.

Related Interview Questions

1
JavaAdvanced#concurrency

What is the Executor framework?

Open
2
JavaIntermediate#concurrency

What is the difference between Callable and Runnable?

Open
3
JavaAdvanced#concurrency

Explain wait(), notify() and notifyAll().

Open