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 CASCAS 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 |