Comprehensive Guide to Java Locks: Synchronized, ReentrantLock, AQS, and Distributed Locks
This article provides an in‑depth overview of Java locking mechanisms, covering lock classifications, the inner workings of the synchronized keyword, ReentrantLock, AbstractQueuedSynchronizer, various lock optimizations, and practical implementations of distributed locks using Redis and Zookeeper.
Preface
Locks are an unavoidable topic in programming. This article thoroughly analyzes Java's synchronized keyword, the lock wrapper class ReentrantLock , the AbstractQueuedSynchronizer (AQS), and distributed locks, explaining their principles, source code, and usage scenarios.
Lock Classification
Optimistic lock – low contention, short execution time.
Pessimistic lock – high contention, long execution time.
Fair lock – threads acquire the lock in arrival order.
Unfair lock – threads acquire the lock randomly.
Exclusive lock – held by a single thread.
Shared lock – held by multiple threads.
Reentrant lock – the owning thread can reacquire the lock.
Spin lock – retries a limited number of times without yielding the CPU, suitable for low‑contention scenarios.
Synchronized
The JVM built‑in synchronization tool, originally inefficient but heavily optimized in later JDK versions.
Lock Objects
Class or static methods – lock the class object.
Instance methods or this – lock the instance object.
Implementation Principle
Synchronized is implemented using the bytecode instructions monitorenter and monitorexit .
monitorenter acquires the monitor, increments the lock counter, and blocks other threads if the counter is already non‑zero.
monitorexit releases the monitor, decrements the counter, and fully releases the lock when the counter reaches zero.
Lock Optimizations
Lock coarsening – merges adjacent lock regions into a larger lock.
Lock elimination – removes unnecessary locks via JIT escape analysis.
Biased locking – avoids lock acquisition overhead when a lock is used by a single thread without contention.
Lightweight locking – uses CAS on the object’s Mark Word to acquire a lock without OS mutexes.
Spin (busy‑waiting) – repeatedly attempts to acquire a lock while keeping the CPU busy.
Adaptive spinning – adjusts spin duration based on previous acquisition success.
Heavyweight lock – falls back to OS mutex when contention is high.
Structure of a Synchronized Object
The object header consists of the Mark Word (hash code, GC age, lock bits, biased‑lock flag) and, for arrays, a class pointer and length field.
Lock Upgrade Process
Object is ordinary – Mark Word stores hash code, lock flag = 01, biased flag = 0.
Thread A acquires a biased lock – lock flag stays 01, biased flag becomes 1, Mark Word records A’s thread ID.
Thread A re‑enters – sees its own ID and continues without further synchronization.
Thread B attempts – CAS tries to acquire; if it fails, the lock upgrades to lightweight.
Lightweight lock fails – thread spins.
Spin fails – lock upgrades to heavyweight, blocking other threads.
java.util.concurrent.locks Core Classes
LockSupport provides low‑level lock primitives implemented by the Unsafe class via native methods:
public native void unpark(Object var1);
public native void park(boolean var1, long var2);ReentrantLock’s logic is delegated to its internal Sync class:
public void lock() { sync.lock(); }
// Fair lock
final void lock() { acquire(1); }
// Non‑fair lock
final void lock() { if (compareAndSetState(0,1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }ReadWriteLock solves the multiple‑reader‑single‑writer problem, while StampedLock introduces an optimistic read mode that allows concurrent writes at the cost of validation.
Key Elements of a Lock Implementation
A state variable (0 = unlocked, 1 = locked, >1 = re‑entrant).
Reference to the owning thread.
Support for blocking and unparking threads (via LockSupport ).
A queue (CLH queue) that holds waiting threads, implemented with CAS.
AQS Core
AQS uses a volatile int state and a FIFO CLH queue to manage exclusive and shared acquisition, providing methods such as tryAcquire , tryRelease , tryAcquireShared , and tryReleaseShared .
private volatile int state;
protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); }Exclusive mode is used by locks like ReentrantLock ; shared mode is used by constructs such as Semaphore , CountDownLatch , and ReadWriteLock .
ReentrantLock Details
Internal structure includes a reference to AbstractQueuedSynchronizer .
Default is a non‑fair lock.
Lock acquisition uses CAS on state and sets the exclusive owner thread.
Re‑entrance increments state ; unlocking decrements it and wakes the next waiting thread.
Fair lock checks the queue before attempting acquisition.
Timeout acquisition uses tryAcquireNanos with park timeout.
ReentrantReadWriteLock
Write lock acquisition checks exclusive count and uses CAS; read lock acquisition increments the shared count. Lock downgrade (write → read) is necessary for visibility guarantees.
protected final boolean tryAcquire(int acquires) { /* write lock logic */ }Distributed Locks
Distributed locks coordinate across multiple JVMs. Common implementations use Redis or Zookeeper.
Redis example (Jedis API):
jedisClientUtil.set(lockKey.toString(), CLIENT_ID + Thread.currentThread().getId(),
JedisClientUtil.SetPremise.NX, JedisClientUtil.ExpireType.Milliseconds, unit.toMillis(expiration)); private static final String DELETE_SCRIPT =
"if redis.call('get',KEYS[1]) == ARGV[1] then\n" +
" return redis.call('del',KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";Key considerations: always set an expiration, release the lock on completion or error, and decide whether other threads may release the lock.
Redisson provides an auto‑renewal mechanism based on a time‑wheel scheduler.
Conclusion
The article walks through lock fundamentals from the basic synchronized keyword to JDK concurrency utilities and finally to distributed lock solutions, offering a complete reference for developers dealing with concurrency in Java.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
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.