java多線程之ReentrantLock非公平鎖源碼解析

前言

上一篇咱們分析了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、公平鎖和非公平鎖的區別

  1. 公平鎖和非公平鎖的區別,是在獲取鎖的機制上。
  2. 公平鎖只有當前線程在隊列的頭部且鎖是空閒的才能獲取鎖。
  3. 非公平鎖只要鎖是空閒的,當前線程就可以直接獲取鎖。
  4. 非公平鎖在嘗試獲取鎖失敗後,纔會像公平鎖一樣,在隊列排隊獲取鎖。

結束語

本篇結束了非公平鎖的源碼分析,並且總結了“獨佔鎖”ReentrantLock公平鎖和非公平鎖的區別,下一篇將分析共享鎖ReentrantReadWriteLock。

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