Java中ReentrantLock底層原理

ReentrantLock底層原理

ReentranLock是一個支持重入的獨佔鎖,在java.util.concurrent包中,底層就是基於AQS實現的,因此下面會設計到AQS的一些東西,若是還不瞭解的能夠先看這篇 Java AQS底層原理解析 瞭解一下。java

  • Sync類segmentfault

    在源碼中能夠看到ReentrantLock類自己並無繼承AQS,而是建立了一個內部類Sync來繼承AQS,而ReentrantLock類自己的那些方法都是調用Sync裏面的方法來實現,而Sync自己本身也是一個抽象類,它還有兩個子類,分別是NonfairSyncFairSync,對鎖各類實際的實現其實在這兩個類中實現,顧名思義,這兩個類分別實現了非公平鎖和公平鎖,在建立ReentrantLock時能夠進行選擇。函數

    // 默認構造函數是建立一個非公平鎖
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    
    // 接受一個boolean參數,true是建立公平鎖,false是非公平鎖
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
  • lock()ui

    • 會調用Sync類中的lock()方法,因此須要看建立的是公平鎖仍是非公平鎖this

      public void lock() {
          sync.lock();
      }
    • 非公平鎖中的lock()方法,先試用CAS的方式更新AQS中的state的狀態,默認是0表明沒有被獲取,當前線程就能夠獲取鎖,而後把state改成1,接着把當前線程標記爲持有鎖的線程,若是if中的操做失敗就表示鎖已經被持有了,就會調用acquire()方法線程

      final void lock() {
          if (compareAndSetState(0, 1))
              setExclusiveOwnerThread(Thread.currentThread());
          else
              acquire(1);
      }
    • acquire()方法是AQS中的那個方法,這裏面調用子類實現的tryAcquire()方法,最終是調用到Sync類中的nonfairTryAcquire()方法,能夠看到先判斷state是否是0,也就是能不能獲取鎖,若是不能則判斷請求鎖的線程和持有鎖的是否是同一個,若是是的話就把state的值加1,也就是實現了重入鎖設計

      public final void acquire(int arg) {
          if (!tryAcquire(arg) &&
              acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
              selfInterrupt();
      }
      
      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;
      }
    • 重寫的tryAcquire()方法,上面非公平鎖是調用的Sync裏的tryAcquire()方法,而公平鎖則在子類NonfairSync中重寫了這個方法,注意if(c==0)判斷中的代碼,也就是線程搶奪鎖的時候會調用hasQueuedPredecessors()方法,這個方法會判斷隊列中有沒有已經先等待的線程了,若是有則當前線程不會搶到鎖,這就實現了公平性,上面nonfairTryAcquire()方法則沒有這種判斷,因此後來的線程可能會比先等待的線程先拿到鎖code

      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;
      }
      
      public final boolean hasQueuedPredecessors() {
          // The correctness of this depends on head being initialized
          // before tail and on head.next being accurate if the current
          // thread is first in queue.
          Node t = tail; // Read fields in reverse initialization order
          Node h = head;
          Node s;
          return h != t &&
              ((s = h.next) == null || s.thread != Thread.currentThread());
      }
  • tryLock()繼承

    這個方法是嘗試去獲取鎖,若是成功返回true,失敗則返回false。會發現調用的就是上面Sync中的nonfairTryAcquire()方法隊列

    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
  • unlock()

    這個方法是釋放鎖,最終會調用到Sync類中的tryRelease()方法。在這個方法裏面會對state減1,若是減1以後爲0就表示當前線程持有次數完全清空了,須要釋放鎖

    public void unlock() {
        sync.release(1);
    }
    
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
            return true;
        }
        return false;
    }  
    
    protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
                  throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }

總結:

若是看了 Java AQS底層原理解析 這篇文章,就會發現其實JUC中的不少鎖都是在AQS的基礎上實現的,並且最複雜的邏輯也是在AQS中實現的,這些鎖只是在它的基礎上實現本身的需求。

相關文章
相關標籤/搜索