Understanding Java Locks: Optimistic vs Pessimistic, Spin Locks, and ReentrantLock
This article explains the various types of locks provided by Java, compares optimistic and pessimistic locking, introduces spin locks and adaptive spin locks, details lock states such as biased, lightweight, and heavyweight, and examines fair versus non‑fair, reentrant versus non‑reentrant, and exclusive versus shared locks with source code references.
Java offers a rich set of locks, each suited to different scenarios; this article reviews lock‑related source code (from JDK 8) and usage patterns, introducing the main lock concepts and their appropriate applications.
1. Optimistic Lock vs Pessimistic Lock
Optimistic locks assume low contention and avoid acquiring a lock during reads, using CAS (Compare‑And‑Swap) for updates, while pessimistic locks acquire a lock (e.g., synchronized or Lock implementations) before accessing data.
Optimistic locking is implemented via AtomicInteger.incrementAndGet(), which relies on unsafe.getAndAddInt() and ultimately on compareAndSwapInt(). The article outlines the three operands of CAS (V, A, B) and discusses the ABA problem, long spin times, and the limitation to a single shared variable.
2. Spin Lock vs Adaptive Spin Lock
Spin locks keep a thread busy looping while waiting for a lock to become free, avoiding the overhead of thread suspension. Adaptive spin locks adjust the spin count based on recent lock acquisition history, allowing longer spins when they are likely to succeed.
3. No‑Lock, Biased Lock, Lightweight Lock, Heavyweight Lock
These are the four lock states for synchronized. The article explains object headers ( Mark Word and Klass Pointer) and the role of the Monitor. It describes how biased locks avoid CAS when a lock is repeatedly acquired by the same thread, lightweight locks use CAS and spinning, and heavyweight locks fall back to OS mutexes.
4. Fair Lock vs Non‑Fair Lock
Fair locks grant access in request order using a queue, while non‑fair locks allow a thread to acquire the lock immediately if it becomes available, potentially overtaking waiting threads. Source code of ReentrantLock shows the only difference is the call to hasQueuedPredecessors() in the fair implementation.
5. Reentrant Lock vs Non‑Reentrant Lock
Reentrant (recursive) locks let the same thread acquire the same lock multiple times; ReentrantLock and synchronized are examples. Non‑reentrant locks would deadlock in nested calls. The article compares the internal state counter logic of ReentrantLock and a hypothetical NonReentrantLock.
6. Exclusive Lock vs Shared Lock
Exclusive locks (e.g., ReentrantLock) allow only one thread to hold the lock, while shared locks (e.g., the read lock of ReentrantReadWriteLock) permit multiple concurrent readers. The article explains how ReentrantReadWriteLock encodes read and write counts in a single 32‑bit state variable.
Overall, the article provides a comparative analysis of common Java locks, their underlying implementations, and guidance on selecting the appropriate lock for a given scenario.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Big Data Technology & Architecture
Wang Zhiwu, a big data expert, dedicated to sharing big data technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
