Java Locks β
π§© 1. What Is a "Lock"? β
A lock is a mechanism in multithreaded concurrent programming used to control access to shared resources.
Core goal: Prevent multiple threads from modifying the same data simultaneously, which could cause data inconsistency (thread-safety issues).
π― Real-world Analogy β
Imagine you and others share a folder (a shared resource):
- Without a lock: you both edit a file at the same time β the file gets corrupted
- With a lock: when one person edits, others must wait
Thatβs the intuitive idea behind a βlock.β
βοΈ 2. Types of Locks in Java β
Java provides multiple locking mechanismsβfrom language-level features to library-level APIs:
Level | Mechanism | Description |
---|---|---|
Syntax level | synchronized | The most common keyword (implicit lock) |
API level | java.util.concurrent.locks.Lock | Explicit lock (e.g., ReentrantLock ) |
Atomic classes | java.util.concurrent.atomic.* | Lock-free (CAS-based optimistic lock) |
Letβs explore them one by one π
π§± 1οΈβ£ synchronized
β The Intrinsic (Monitor) Lock β
synchronized
is the classic synchronization mechanism. Simple usage:
synchronized (obj) {
// critical section
}
It relies on a Monitor lock inside the object header, which is a type of pessimistic lock (explained later).
You can also use it on methods:
public synchronized void add() { ... }
At the bytecode level, the compiler generates monitorenter
and monitorexit
instructions.
βοΈ 2οΈβ£ Lock
Interface and Implementations (Explicit Locks) β
Introduced in JDK 1.5: java.util.concurrent.locks.Lock
. It provides more flexibility than synchronized
:
Lock lock = new ReentrantLock();
lock.lock();
try {
// critical section
} finally {
lock.unlock();
}
Advantages:
- Can attempt to acquire a lock (
tryLock()
) - Can acquire interruptibly (
lockInterruptibly()
) - Supports fair and unfair locking
Lock
implementations are usually built on top of AQS (AbstractQueuedSynchronizer).
π‘ 3οΈβ£ CAS (Compare-And-Swap) and Atomic Classes β
CAS is a lock-free mechanism, based on optimistic locking.
Example:
AtomicInteger i = new AtomicInteger(0);
i.incrementAndGet(); // internally uses CAS
CAS is a hardware-level atomic instruction: It compares a current value in memory with an expected value, and updates only if they match; otherwise, it retries.
π§ 3. Lock Classifications (Important!) β
When discussing Java locks, youβll often hear about:
Pessimistic vs Optimistic Locks Fair vs Unfair Locks Reentrant vs Non-reentrant Locks Read/Write Locks Spin Locks
Letβs clarify them π
π 1οΈβ£ Pessimistic Lock β
- Assumes conflicts are likely, so it locks first, then operates.
- Typical examples:
synchronized
,ReentrantLock
Example:
synchronized (this) {
count++;
}
Other threads must wait for the lock to be released. Safe but potentially slow.
π 2οΈβ£ Optimistic Lock β
- Assumes conflicts are rare, so it operates first, then checks.
- If a conflict occurs, it retries.
Implemented via CAS (Compare-And-Swap)
Simplified example:
while (true) {
int oldValue = atomicInt.get();
int newValue = oldValue + 1;
if (atomicInt.compareAndSet(oldValue, newValue)) {
break; // success
}
// otherwise retry
}
β Advantages: High performance (no blocking) β οΈ Drawback: Under high contention, frequent retries can waste CPU cycles.
π§ 3οΈβ£ Fair vs Unfair Locks β
- Fair lock: Threads acquire the lock in the order they requested it.
- Unfair lock: Threads can βjump the queue,β improving throughput.
ReentrantLock
defaults to unfair, but you can specify:
new ReentrantLock(true); // fair lock
π 4οΈβ£ Reentrant Lock β
A lock is reentrant if the same thread can acquire it multiple times without deadlocking.
Example:
public synchronized void a() {
b(); // re-enters the same lock
}
public synchronized void b() { }
Both synchronized
and ReentrantLock
are reentrant.
π 5οΈβ£ Read/Write Lock β
When reads greatly outnumber writes, ReadWriteLock improves concurrency:
- Multiple threads can read simultaneously
- Writes are exclusive
Example:
ReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock();
...
rwLock.writeLock().lock();
π 6οΈβ£ Spin Lock β
A spin lock doesnβt suspend a thread while waiting for a lock. Instead, it loops repeatedly checking if the lock is available.
This can reduce context switching overhead under low contention.
Javaβs CAS operations embody this βspinningβ concept.
π 4. Relationship and Evolution of Locks (Summary Diagram) β
Lock hierarchy:
βββββββββββββββββββββββββββββββ
β synchronized (pessimistic, intrinsic) β
β ReentrantLock (explicit, reentrant) β
β ReadWriteLock (fine-grained) β
β β
β β AQS (underlying framework) β
β β CAS (hardware-level instruction) β
βββββββββββββββββββββββββββββββ
β
ββ Optimistic Locking (CAS-based)
β‘ 5. One-Line Summary Table β
Type | Description | Typical Implementations |
---|---|---|
Pessimistic | Locks first, prevents conflicts | synchronized , ReentrantLock |
Optimistic | Operate first, check & retry | AtomicInteger , CAS |
Fair | FIFO lock acquisition | ReentrantLock(true) |
Unfair | Allows lock jumping | ReentrantLock(false) |
Reentrant | Same thread can re-lock | synchronized , ReentrantLock |
Read/Write | Read shared, write exclusive | ReentrantReadWriteLock |