1 Overview
ReentrantLock AQS is based on a realization of an exclusive lock , lock fair and unfair lock modes.
The default is to use unfair lock :
public ReentrantLock() {
sync = new NonfairSync();
}
复制代码
You can also specify mode:
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
复制代码
- 1
ReentrantLock
implementsLock
the interface; - 2
ReentrantLock
defines the inner class Sync inherit the AQS:abstract static class Sync extends AbstractQueuedSynchronizer{....}
; - 3
Sync
is an abstract class, there are two implementation classNonfairSync
/FairSync
, it is used to implement a non-fair lock / fair lock .
Official Example:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
复制代码
2 implementation
This article only ReentrantLock of lock/unlock
implementation, analysis of how to achieve an exclusive lock on AQS.
The AQS convention (refer AQS core source code analysis and analytical method ):
- 1 lock: achieve
tryAcquire
, and called when Lockacquire
; - 2 unlock: achieve
tryRelease
, and calls upon UNLOCKrelease
.
2 lock()
ReentrantLock.lock()
It calls Sync.lock()
, and Sync.lock()
is an abstract method, implemented by subclasses.
So NonfairSync
/ FairSync
two classes, necessarily used acquire
method to acquire lock, and implements tryAcquire
methods.
2.1 NonfairSync
2.1.1 lock
- 1 to call
compareAndSetState
the state a value from 0 to 1 replacement, successful, indicating that no other thread currently holds the lock, do not line up directly held. BysetExclusiveOwnerThread
the current thread to an exclusive lock holders. - Otherwise, by 2
acquire
to line up.
final void lock() {
if (compareAndSetState(0, 1)) // 如果当前state==0,则说明没有其他线程持有锁,CAS成功。
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
复制代码
2.1.2 tryAcquire
NonfairSync.tryAcquire
It called directly Sync.nonfairTryAcquire
.
nonfairTryAcquire
Non-fair tryAcquire
implementation, not by AQS.hasQueuedPredecessors
judges are threads in the queue.
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// state == 0,说明没有其他线程持有锁。
if (compareAndSetState(0, acquires)) {
// 将当前线程设置为`独占锁持有者`,tryAcqire成功。
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
/*
如果当前线程正是`独占锁持有者`,叠加state,实现`可重入`,tryAcqire成功。
也就是说AQS的同步列表中,有多个当前线程的节点。
*/
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
复制代码
2.2 FairSync
2.2.1 lock
Do not compareAndSetState
try to directly join the queue AQS synchronization of their own.
final void lock() {
acquire(1);
}
复制代码
2.2.2 tryAcquire
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { // state == 0,说明没有其他线程持有锁。
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
/*
`!hasQueuedPredecessors()` 说明AQS的同步队列中,没有比自己更优先的线程在等待
*/
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
/*
如果当前线程正是`独占锁持有者`,叠加state,实现`可重入`,tryAcqire成功。
也就是说AQS的同步列表中,有多个当前线程的节点。
*/
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
复制代码
FairSync.tryAcquire
More thanNonFairSync.tryAcquire
one more!hasQueuedPredecessors()
judgment, other processes are the same.
3 unlock()
unlock operation NonFairSync
/ FairSync
no distinction, directly in the Sync.
Sync
The unlock
call AQS.release
, and implemented tryRelease
.
public void unlock() {
sync.release(1);
}
复制代码
3.1 tryRelease
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 当前线程不是`独占锁持有者`,抛出异常。
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) { // c == 0 说明锁已经完全释放。
free = true;
// 将当前`独占锁持有者`置空。
setExclusiveOwnerThread(null);
}
// 更新state值
setState(c);
return free;
}
复制代码
4 Summary
NonFairSync
/ FairSync
The basic process is the same, except that:
- 1
NonFairSync
in the lock, will first trycompareAndSetState(0, 1)
to seize the lock, then it failsacquire(1)
;FairSync
directacquire(1)
line. - 2
FairSync
attryAcquire
the time, it is determinedcompareAndSetState(0, acquires)
at the same time, had a pluralityhasQueuedPredecessors()
of determination, for determining whether a synchronization queue than their priority threads.