博客 / 詳情

返回

ReentrantLock 原理解析

ReentrantLock 可重入鎖 字面意思理解為同一線程可以重入加鎖

AbstractQueuedSynchronizer 源碼解析 可以先看這篇文章瞭解AQS原理
內部主要邏輯繼承AQS來實現的,有兩種實現FairSycn、NonfairSync,公平鎖和非公平鎖,默認為非公平鎖。

  • 公平鎖:保證先入隊的先獲得鎖。
  • 非公平鎖:不保證先入隊的先獲得鎖,可能後面的線程先搶到鎖。

image.png

主要實現流程

state值默認為0,當state=0時,線程通過CAS爭搶鎖,獲取到鎖時state值為1,同一個線程多次獲取鎖state值+1,解鎖時-1直到為0時釋放鎖,未獲取到鎖的線程加入CLH隊列阻塞LockSupport.park()等待,鎖釋放時通過CLH隊列關聯喚醒LockSupport.unpark()等待的線程去獲取鎖
image.png
CAS全名compare and swap比較交換,由native方法提供的系統原子性操作,以保證併發發安全性。

  • 公平鎖的實現

    加鎖

    //加鎖
    final void lock() {
      acquire(1);//調用AQS方法
    }
    //AQS方法
    public final void acquire(int arg) {
      if (!tryAcquire(arg) &&//嘗試獲取鎖,抽象方法由子類實現
          acquireQueued(addWaiter(Node.EXCLUSIVE), arg))    
          /* addWaiter 將線程加入等待隊列
           * acquireQueued 嘗試獲取鎖、阻塞
           */
      {
          //中斷
          selfInterrupt();
      }
    }
    //嘗試獲取鎖
    protected final boolean tryAcquire(int acquires) {
      //獲取當前線程
      final Thread current = Thread.currentThread();
      int c = getState();//獲取state值,AQS屬性volatile標記
      if (c == 0) {//鎖空閒狀態
          if (!hasQueuedPredecessors() &&//是否需要排隊
              compareAndSetState(0, acquires)) {//獲取鎖
              setExclusiveOwnerThread(current);//成功獲取,設置鎖owner為當前線程
              return true;//後續不在處理
          }
      }
      else if (current == getExclusiveOwnerThread()) {//當前線程已持有鎖,重入
          int nextc = c + acquires;//state+1
          if (nextc < 0)
              throw new Error("Maximum lock count exceeded");
          setState(nextc);//已持有鎖,直接設置state值
          return true;
      }
      return false;
    }

    解鎖

    //解鎖,ReentrantLock方法
    public void unlock() {
      sync.release(1);//AQS方法
    }
    //AQS解鎖
    public final boolean release(int arg) {
      if (tryRelease(arg)) {//嘗試解鎖
          Node h = head;
          if (h != null && h.waitStatus != 0)//waitStatus=0時不進行unpark(喚醒),next線程可能中斷
              unparkSuccessor(h);//喚醒隊列中的線程去獲取鎖
          return true;
      }
      return false;
    }
    //嘗試解鎖ReentrantLock內部靜態類Sync實現
    protected final boolean tryRelease(int releases) {
      int c = getState() - releases;//state-1
      if (Thread.currentThread() != getExclusiveOwnerThread())
          throw new IllegalMonitorStateException();//非持有鎖的線程進行釋放,非法操作
      boolean free = false;
      if (c == 0) {//持有鎖線程全部釋放
          free = true;
          setExclusiveOwnerThread(null);//持有鎖線程置空
      }
      setState(c);//持有鎖線程直接設置state
      return free;
    }
  • 非公平鎖的實現

    非公平鎖和公平鎖的核心區別是在嘗試獲取鎖方法tryAcquire實現中沒有判斷hasQueuedPredecessors()是否需要排隊,其他邏輯和公平鎖是一致的。
    image.png

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.