ReentrantLock是java1.5中l(wèi)ock框架中Lock接口的一個(gè)實(shí)現(xiàn)類.一個(gè)ReentrantLock的實(shí)例鎖擁有和synchronized相同的行為和語義,并且還擴(kuò)展了其他能力.
ReentrantLock是通過一種什么機(jī)制來實(shí)現(xiàn)鎖的呢?也就是說ReentrantLock到底是鎖住了什么東西來控制線程同步的呢?下面將詳細(xì)講解.
ReentrantLock內(nèi)部實(shí)現(xiàn)了一個(gè)AbstractQueuedSynchronizer的同步器,ReentrantLock就是通過控制這個(gè)AbstractQueuedSynchronizer同步器來實(shí)現(xiàn)多個(gè)線程之間的同步.那么具體的實(shí)現(xiàn)原理是怎么樣的呢?
AbstractQueuedSynchronizer類會(huì)維護(hù)一個(gè)等待隊(duì)列,并且擁有一個(gè)state(volatile修飾)的成員變量屬性,AbstractQueuedSynchronizer就是通過這個(gè)state來控制多個(gè)線程的同步訪問的.當(dāng)ReentrantLock調(diào)用lock()方法時(shí),內(nèi)部實(shí)際調(diào)用的是Sync(AbstractQueuedSynchronizer的實(shí)現(xiàn)類)的lock方法,此方法會(huì)先判斷AbstractQueuedSynchronizer中state屬性的值:如果state!=0,說明當(dāng)前有線程在占用鎖資源,然后接著判斷當(dāng)前占用該鎖資源的線程是否跟當(dāng)前線程是同一個(gè)線程,如果是同一個(gè)線程那么state值就加一,同時(shí)當(dāng)前線程繼續(xù)執(zhí)行,如果不是同一個(gè)線程,那么就會(huì)把當(dāng)前線程加入等待隊(duì)列(并且會(huì)一直嘗試獲取鎖資源).如果state==0,說明當(dāng)前鎖資源是可用,那么直接設(shè)置當(dāng)前線程占用了鎖資源并返回繼續(xù)執(zhí)行.執(zhí)行完成之后,必須要手動(dòng)釋放鎖資源.
下面對ReentrantLock的源碼并相關(guān)類源碼進(jìn)行解讀:
類定義
public class ReentrantLock implements Lock, java.io.Serializable
成員變量
| 修飾符 | 變量名 | 作用 |
|---|---|---|
| private final Sync | sync | 實(shí)際同步鎖控制實(shí)例 |
構(gòu)造方法
無參構(gòu)造方法
無參構(gòu)造方法會(huì)給sync賦值,默認(rèn)賦值為不公平鎖同步(公平鎖,不公平鎖下面會(huì)講)
public ReentrantLock() {
sync = new NonfairSync();
}
有參構(gòu)造方法
參數(shù):
true 公平鎖,線程獲取鎖的順序跟等待的時(shí)間有關(guān),先等待的線程先獲取鎖
false 不公平鎖,線程獲取鎖是隨機(jī)的
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
核心方法講解
lock()方法
public void lock() {
// 調(diào)用Sync(Sync是AbstractQueuedSynchronizer的子類)的lock()方法
// Sync是ReentrantLock的內(nèi)部類,同時(shí)在ReentrantLock中有兩種實(shí)現(xiàn)方式
// 1. FairSync(公平實(shí)現(xiàn))
// 2. NonFairSync(不公平實(shí)現(xiàn))
sync.lock();
}
-- ------------------------------------------------------ --
-- ---------------FairSync獲取鎖的實(shí)現(xiàn)-------------------- --
-- ------------------------------------------------------ --
/**
* FairSync的lock方法實(shí)現(xiàn)
**/
final void lock() {
// acquire方法是AbstractQueuedSynchronizer中的方法
// 此方法會(huì)調(diào)用tryAcquire(int)方法來試圖獲取鎖資源
acquire(1);
}
/**
* AbstractQueuedSynchronizer中acquire()方法的實(shí)現(xiàn)
**/
public final void acquire(int arg) {
// 試圖獲取鎖資源(會(huì)調(diào)用對應(yīng)實(shí)現(xiàn)的tryAcquire()方法),
// 不成功則加入等待隊(duì)列并獲取隊(duì)列(addWaiter()會(huì)將當(dāng)前線程加入到等待隊(duì)列尾部)
// acquireQueued()(不知道怎么說,等會(huì)直接講代碼)
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
* FairSync中tryAcquire()的實(shí)現(xiàn)
* 返回
* true: 獲取鎖成功
* false: 獲取鎖不成功
**/
protected final boolean tryAcquire(int acquires) {
// 獲取當(dāng)前線程
final Thread current = Thread.currentThread();
// 獲取鎖資源的狀態(tài)
// 0: 說明當(dāng)前鎖可立即獲取,在此種狀態(tài)下(又是公平鎖)
// >0并且當(dāng)前線程與持有鎖資源的線程是同一個(gè)線程則state + 1并返回true
// >0并且占有鎖資源的不是當(dāng)前線程,則返回false表示獲取不成功
int c = getState();
if (c == 0) {
// 在鎖可以立即獲取的情況下
// 首先判斷線程是否是剛剛釋放鎖資源的頭節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)(線程的等待先后順序)
// 如果是等待時(shí)間最長的才會(huì)馬上獲取到鎖資源,否則不會(huì)(這也是公平與不公平的主要區(qū)別所在)
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //線程可以遞歸獲取鎖
int nextc = c + acquires;
// 超過int上限值拋出錯(cuò)誤
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
/**
* AbstractQueuedSynchronizer中acquireQueued()方法講解
**/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 注意這里的無限循環(huán)(表現(xiàn)出來就是等待的一個(gè)過程)
for (;;) {
// 獲得前一個(gè)非null節(jié)點(diǎn)
final Node p = node.predecessor();
// 如果前任節(jié)點(diǎn)是頭結(jié)點(diǎn)(頭節(jié)點(diǎn)是表示獲取到了資源鎖的節(jié)點(diǎn))
// 并且試圖獲取鎖資源(只有在p節(jié)點(diǎn)release()掉鎖資源才會(huì)獲取成功)
// 如果獲取鎖資源成功,就將此線程節(jié)點(diǎn)設(shè)置為頭結(jié)點(diǎn),并把p節(jié)點(diǎn)的引用斷開
// 獲取鎖成功就退出循環(huán)
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 如果獲取資源失敗了,那就先判斷線程是否需要被阻塞,需要就阻塞線程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
// 繼續(xù)循環(huán)等待
}
} finally {
// 如果獲取鎖資源失敗了,
// 那么就把線程的等待狀態(tài)設(shè)置為cancelled(此狀態(tài)的線程不會(huì)再獲得鎖資源)
if (failed)
cancelAcquire(node);
}
}
-- ------------------------------------------------------ --
-- ---------------NonFairSync獲取鎖的實(shí)現(xiàn)----------------- --
-- ------------------------------------------------------ --
/**
* lock()方法實(shí)現(xiàn)
**/
final void lock() {
// 如果鎖空閑則立即獲取鎖資源,設(shè)置鎖資源的當(dāng)前占用線程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// acquire()過程跟FairSync是一樣的,
// 主要區(qū)別在于NonFairSync的tryAcqure()有不同的實(shí)現(xiàn)
acquire(1);
}
/**
* tryAcquire()方法實(shí)現(xiàn)
* 調(diào)用的nonfairTryAcquire()方法,這是父類Sync中的方法實(shí)現(xiàn)
**/
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
/**
* Sync中的nonfairTryAcquire()方法實(shí)現(xiàn)
* 這個(gè)跟公平類中的實(shí)現(xiàn)主要區(qū)別在于不會(huì)判斷當(dāng)前線程是否是等待時(shí)間最長的線程
**/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 跟FairSync中的主要區(qū)別,不會(huì)判斷hasQueuedPredecessors()
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;
}
unlock()方法
釋放線程占用的鎖
public void unlock() {
// 調(diào)用Sync中的release()方法,所以公平和不公平類釋放鎖是一樣的
// 實(shí)際調(diào)用AbstractQueuedSynchronizer中的release()
sync.release(1);
}
/**
* AbstractQueuedSynchronizer中的release()
**/
public final boolean release(int arg) {
// 釋放鎖資源,子類會(huì)重寫這個(gè)方法(在這里就是調(diào)用的Sync中tryRelease())
if (tryRelease(arg)) {
// 釋放鎖資源成功后,會(huì)執(zhí)行一個(gè)喚醒后續(xù)線程(喚醒一個(gè))的操作
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
/**
* Sync中tryRelease()
**/
protected final boolean tryRelease(int releases) {
// 修改當(dāng)前鎖的狀態(tài)
// 如果一個(gè)線程遞歸獲取了該鎖(也就是state != 1), 那么c可能不等0
// 如果沒有線程遞歸獲取該鎖,則c == 0
int c = getState() - releases;
// 如果鎖的占有線程不等于當(dāng)前正在執(zhí)行釋放操作的線程,則拋出異常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// c == 0,表示當(dāng)前線程釋放鎖成功,同時(shí)表示遞歸獲取了該鎖的線程已經(jīng)執(zhí)行完畢
// 則設(shè)置當(dāng)前鎖狀態(tài)為free,同時(shí)設(shè)置鎖的當(dāng)前線程為null,可以讓其他線程來獲取
// 同時(shí)也說明,如果c != 0,則表示線程遞歸占用了鎖資源,
// 所以鎖的當(dāng)前占用線程依然是當(dāng)前釋放鎖的線程(實(shí)際沒有釋放)
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
// 重新設(shè)置鎖的占有數(shù)
setState(c);
return free;
}
條件鎖的操作
public Condition newCondition() {
return sync.newCondition();
}
這里不對源碼進(jìn)行解讀,只對原理進(jìn)行一個(gè)說明,上述函數(shù)實(shí)際上是執(zhí)行了一個(gè)new ConditionObject();的操作,
這個(gè)類是同步器中的一個(gè)內(nèi)部類,這個(gè)類內(nèi)部是維護(hù)了一個(gè)條件隊(duì)列,條件鎖的操作也是針對這個(gè)條件隊(duì)列的一個(gè)操作.