前言
上一篇咱們分析了ReentrantLock公平鎖的獲取和釋放的源碼,本篇再看非公平鎖的源碼就輕鬆多了,上一篇沒看的建議先去看公平鎖的源碼分析。
1、獲取非公平鎖
下面是非公平鎖獲取鎖的源碼,是在ReentrantLock.java的NonfairSync類中。
final void lock() {
//通過CAS判斷"鎖"是不是空閒狀態
if (compareAndSetState(0, 1))
//設置“當前線程”爲“鎖”的持有者
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire()在AbstractQueuedSynchronizer(AQS)抽象類中定義的,它的源碼如下:
//注意,acquire方法中,tryAcquire方法是由公平鎖類和非公平鎖類自己實現的
//addWaiter、acquireQueued、selfInterrupt方法是由AQS自己實現的
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
1.1、tryAcquire方法
非公平鎖的tryAcquire()在ReentrantLock.java的NonfairSync類中實現,源碼如下:
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
nonfairTryAcquire()在ReentrantLock.java的Sync類中實現,源碼如下:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//細心的同學可能已經發現了,這裏比公平鎖的少了一行代碼
//少了的那行代碼是:!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;
}
2、釋放非公平鎖
釋放非公平鎖和釋放公平鎖是一樣的,這裏不重複說明,忘記了的,可以再回去看看公平鎖的釋放方法。
3、公平鎖和非公平鎖的區別
- 公平鎖和非公平鎖的區別,是在獲取鎖的機制上。
- 公平鎖只有當前線程在隊列的頭部且鎖是空閒的才能獲取鎖。
- 非公平鎖只要鎖是空閒的,當前線程就可以直接獲取鎖。
- 非公平鎖在嘗試獲取鎖失敗後,纔會像公平鎖一樣,在隊列排隊獲取鎖。
結束語
本篇結束了非公平鎖的源碼分析,並且總結了“獨佔鎖”ReentrantLock公平鎖和非公平鎖的區別,下一篇將分析共享鎖ReentrantReadWriteLock。