Java中的公平鎖和非公平鎖實現詳解


在ReentrantLock中包含了公平鎖和非公平鎖兩種鎖,通過查看源碼可以看到這兩種鎖都是繼承自Sync,而Sync又繼承自AbstractQueuedSynchronizer,而AbstractQueuedSynchronizer又繼承自AbstractOwnableSynchronizer,下面是類的繼承關系圖:


其中AbstractOwnableSynchronizer是提供了設置占用當前鎖的線程信息的方法,主要的鎖的實現還是在AbstractQueuedSynchronizer中實現的,在AbstractQueuedSynchronizer中通過CLH隊列實現了多線程鎖的排隊使用,但是該隊列的實現並不能保證鎖的公平競爭,但是在某些業務場景中會需要保證先到的線程先得到鎖,所以就有了公平鎖和非公平鎖的誕生。

通過分析ReentrantLock中的公平鎖和非公平鎖的實現,其中tryAcquire是公平鎖和非公平鎖實現的區別,下面的兩種類型的鎖的tryAcquire的實現,從中我們可以看出在公平鎖中,每一次的tryAcquire都會檢查CLH隊列中是否仍有前驅的元素,如果仍然有那么繼續等待,通過這種方式來保證先來先服務的原則;而非公平鎖,首先是檢查並設置鎖的狀態,這種方式會出現即使隊列中有等待的線程,但是新的線程仍然會與排隊線程中的對頭線程競爭(但是排隊的線程是先來先服務的),所以新的線程可能會搶占已經在排隊的線程的鎖,這樣就無法保證先來先服務,但是已經等待的線程們是仍然保證先來先服務的,所以總結一下公平鎖和非公平鎖的區別:

1、公平鎖能保證:老的線程排隊使用鎖,新線程仍然排隊使用鎖。
2、非公平鎖保證:老的線程排隊使用鎖;但是無法保證新線程搶占已經在排隊的線程的鎖。

公平鎖的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) {
// !hasQueuedPredecessors()保證了不論是新的線程還是已經排隊的線程都順序使用鎖
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
非公平鎖的

/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM