Locks and Synchronization

Choose Java locking and synchronization primitives that protect shared state without creating hidden contention or brittle coordination.

Java offers several ways to coordinate shared mutable state, from synchronized blocks to explicit locks, atomic variables, and higher-level synchronizers. The hard part is not learning the APIs. The hard part is picking the smallest coordination mechanism that preserves correctness without turning the system into a contention problem.

This section is about those trade-offs. Some workloads need only visibility guarantees or one atomic update. Others need lock striping, read-write coordination, or phase-based synchronization across many threads.

The child pages move from basic locking choices into advanced mechanisms and synchronizers in java.util.concurrent. Read them as coordination design choices, not just API reference entries.

In this section

  • Advanced Locking Mechanisms
    Use advanced Java locks when intrinsic synchronization is too blunt and you need clearer control over fairness, read/write access, or optimistic reads.
    • ReentrantLock in Java
      Use `ReentrantLock` in Java when interruption, timed acquisition, fairness, or explicit lock management matter more than `synchronized` simplicity.
    • ReentrantReadWriteLock in Java
      Use `ReentrantReadWriteLock` in Java when read-heavy contention patterns justify separate read and write access paths.
    • StampedLock in Java
      Use `StampedLock` in Java for optimistic reads and specialized contention patterns when simpler locking is too coarse.
    • Optimistic Locking Techniques in Java Concurrency
      Use optimistic locking techniques in Java when read-mostly access patterns justify retries and validation over heavier lock contention.
  • Synchronizers in `java.util.concurrent`
    Use Java synchronizers such as latches, barriers, semaphores, phasers, and exchangers when threads must coordinate phases or resource access explicitly.
    • CountDownLatch in Java
      Use `CountDownLatch` in Java when one thread must wait for a fixed number of one-time events or worker completions.
    • CyclicBarrier in Java
      Use `CyclicBarrier` in Java when a fixed group of worker threads must repeatedly meet at the same phase boundary.
    • Semaphore in Java
      Use `Semaphore` in Java to bound concurrent access to scarce resources and make admission control explicit.
    • Exchanger in Java
      Use `Exchanger` in Java when two threads need a rendezvous point to swap data without broader shared-state coordination.
    • Phaser in Java
      Use `Phaser` in Java when participants can register dynamically across multiple synchronization phases instead of staying fixed.
  • Understanding the `volatile` Keyword and Atomic Variables in Java Concurrency
    Understand when `volatile` is enough in Java, when atomic variables are better, and when neither replaces real synchronization.
Revised on Thursday, April 23, 2026