ReentrantLock中公平鎖與非公平鎖的實現原理

在java中,一般的鎖實現都要藉助隊列同步器AbstractQueuedSynchronizer,繼承它並重寫其指定的方法,隨後調用同步器提供的模板方法,模板方法最終會再調用到自己重寫的方法。tryAcquire(int acquires)就是其中的一個抽象方法,需要重寫。


ReentrantLock公平鎖與非公平鎖的實現原理區別就是抽象方法tryAcquire的實現不同。公平鎖的同步器tryAcquire方法如下:

//公平鎖
    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;
    }
}

非公平鎖的同步器tryAcquire方法如下

protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

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;
}

總結:公平鎖與非公平鎖相比,唯一不同的位置爲判斷條件多了hasQueuedPredecessors方法,即加入了同步隊列的當前節點是否有前驅節點的判斷,如果該方法返回true,則表示有線程比當前線程更早地請求獲取鎖,因此需要等待前驅節點下次呢很難過獲取並釋放鎖之後才能繼續獲取鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章