AbstractQueuedSynchronizer (AQS) Overview
AQS serves as a framework for blocking locks and synchronizer utilities. Key characteristics include:
- State Management: Uses
state(32-bit int) to represent resource status (exclusive/shared mode) - FIFO Queue: Maintains a wait queue for blocked threads
- Condition Variables: Supports multipel condition variables for signaling
Core Methods to Implement
protected boolean tryAcquire(int arg)
protected boolean tryRelease(int arg)
protected int tryAcquireShared(int arg)
protected boolean tryReleaseShared(int arg)
protected boolean isHeldExclusively()
Custom Lock Implemantation Example
class CustomLock implements Lock {
private final Sync sync = new Sync();
static class Sync extends AbstractQueuedSynchronizer {
protected boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
protected boolean tryRelease(int releases) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}
// Lock interface methods implementation
public void lock() { sync.acquire(1); }
public void unlock() { sync.release(1); }
// ... other methods
}
ReentrantLock Implementation
Nonfair Lock Mechanics
Lock Acquisition:
- Direct CAS attempt on
state(0→1) - On failure, anqueue thread via
acquire()
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
Lock Release:
- Sets
state = 0andowner = null - Unparks successor thread from queue
Reentrancy Mechanism
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// Initial acquisition
}
else if (current == getExclusiveOwnerThread()) {
// Reentrant acquisition
setState(c + acquires);
return true;
}
return false;
}
Fair vs Nonfair Locks
Key Difference: Fair locks check queue before acquisition
protected final boolean tryAcquire(int acquires) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
// ...
}
Condition Variables
Await Process:
- Adds node to condition queue
- Fully releases lock
- Parks thread
Signal Process:
- Transfers node from condition queue to sync queue
- Unparks thread when lock becomes available
public final void await() throws InterruptedException {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
}
// ...
}