ReentrantLock類是屬于java.util.concurrent的。實現(xiàn)了Lock, java.io.Serializable兩個接口,是一個可重入的互斥鎖,所謂可重入是線程可以重復(fù)獲取已經(jīng)持有的鎖。
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
abstract static class Sync extends AbstractQueuedSynchronizer
ReentrantLock實現(xiàn)鎖的機(jī)制是通過Sync進(jìn)行操作的。Sync類是繼承AbstractQueuedSynchronizer類的。這也就表明ReentrantLock是基于AQS的實現(xiàn)的?!?/p>
Sync,FairSync和NonFairSync都是ReentrantLock的靜態(tài)內(nèi)部類。FairSync和NonFairSync又是Sync具體實現(xiàn)類,分別對應(yīng)的是公平鎖和非公平鎖,公平主要是指按照FIFO原則順序獲取鎖,非公平可以根據(jù)定義的規(guī)則來選擇獲得鎖。
NonFairSync 源碼分析
非公平鎖NonFairSync是ReentrantLock默認(rèn)的實現(xiàn)方式。這里可以看一下它的lock實現(xiàn)過程:
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
- 首先通過
CAS更新state狀態(tài),如果更新成功,則獲取鎖,設(shè)定當(dāng)前線程為鎖的擁有者。
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
- 如果更新失敗,表明當(dāng)前鎖被其他線程占有。則會調(diào)用
acquire(1)方法。acquire具體實現(xiàn)如下:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
tryAcquire過程,將再次嘗試獲取鎖,其中tryAcquire在靜態(tài)內(nèi)部類NonfairSync類中被重寫,具體的實現(xiàn)是Sync的nonfairTryAcquire方法:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
其主要過程是先獲取state的值,如果等于0,則通過CAS更新state的值。如果state不為0,則判斷當(dāng)前線程是否是鎖的持有者,如果是,則將state加1,返回true。
如果tryAcquire仍然失敗的話,首先會調(diào)用addWaiter(Node.EXCLUSIVE),將當(dāng)前線程加入到等待隊列的尾部。然后會調(diào)用acquireQueued方法,acquireQueued的作用主要是用來阻塞線程的:
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
這里是一個循環(huán)自旋操作,在阻塞線程之前,首先判斷線程自身前面的節(jié)點是否是head節(jié)點,如果是,則重新去獲取鎖,獲取成功后,返回,并取消不斷獲取的過程。如果不是,調(diào)用shouldParkAfterFailedAcquire方法去判斷是否應(yīng)該阻塞當(dāng)前線程,主要是通過節(jié)點的waitStatus來進(jìn)行判斷。
FairSync 源碼分析
公平鎖FairSync和非公平鎖NonFairSync的實現(xiàn)很相似,這里比較一下兩者的差別。
-
FairSync的lock方法中沒有像NonFairSync中先去通過CAS操作state去獲取鎖,而是直接通過tryAcquire去獲取鎖。
final void lock() {
acquire(1);
}
-
FairSync版本tryAcquire在獲取鎖的過程中,需要先判斷隊列中是否有其他等待的線程,如果沒有,才回去嘗試獲取鎖。
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
unlock() 釋放鎖
釋放鎖沒有區(qū)分公平和非公平的。主要的工作就是減小state的值。當(dāng)state等0的時候,釋放鎖并喚醒隊里中其他線程來獲取鎖。
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
總結(jié)
-
ReentrantLock是通過AQS的state字段來判斷所是否被占用。 -
公平與非公平的差別是在于獲取鎖的方式是否是按照順序的。 -
state操作是通過CAS實現(xiàn)的。通過隊列來實現(xiàn)因搶占鎖被阻塞的隊列。 - 在阻塞線程的過程中,
AQS有自旋的過程,并非是獲取不到鎖就直接阻塞。
如有紕漏,還望指正。