乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      AQS --- 漸入佳境

       貪挽懶月 2022-06-20 發(fā)布于廣東

      上一講了解了 AQS 是什么,接下來看看它到底是怎樣的結(jié)構(gòu)。

      一. 工作原理

      AQS 使用一個 volatile 的 int 類型的成員變量來表示同步狀態(tài),通過內(nèi)置的 FIFO 隊列來完成資源獲取和排隊工作,將每條要去搶占資源的線程封裝成一個 node 節(jié)點來實現(xiàn)鎖的分配,通過 CAS 來完成對 state 值的修改。

      HashMap 進(jìn)行 put 的時候,也不是直接存儲 key value 鍵值對,而是將 key value 鍵值對封裝成 Node 節(jié)點,然后用數(shù)組 + 鏈表 + 紅黑樹存儲 Node。AQS 也類似,將要搶占資源的 Thread 封裝成 Node節(jié)點。

      二. 相關(guān)源碼:

      public abstract class AbstractQueuedSynchronizer
          extends AbstractOwnableSynchronizer
          implements java.io.Serializable {
         
          static final class Node {
             ……
             volatile int waitStatus;
             volatile Node prev;
             volatile Node next;
             volatile Thread thread;
             ……
          }

          private transient volatile Node head;
          private transient volatile Node tail;

          /**
           * The synchronization state.
           */
          private volatile int state;
      }

      看到這個是不是就清清楚楚明明白白真真切切了。首先 AQS 外層是 state + CLH 隊列,state 表示同步的狀態(tài),默認(rèn)是0,為0時表示可以獲取鎖,不為0時,線程就得老老實實到隊列中排隊去;CLH 隊列就是一個有頭結(jié)點和尾結(jié)點的雙端隊列,如下圖:

                 +------+  prev +-----+       +-----+
            head |      | <---- |     | <---- |     |  tail
                 +------+       +-----+       +-----+

      AQS 的內(nèi)層是一個 Node內(nèi)部類,這個 Node 類主要有兩個指針 prev 和 next、一個 waitStatus 表示線程的狀、,一個 Thread 類型的變量保存等待的線程。

      三. 從 ReentrantLock 看 AQS:

      之前說了 AQS 是 JUC 并發(fā)包的基石,那就從我們接觸最多的 ReentrantLock 入手,揭開它的神秘面紗。

      先來看看 ReentrantLock 的結(jié)構(gòu)圖:

      結(jié)構(gòu)圖

      首先它實現(xiàn)了 Lock 接口,其內(nèi)部主要是一個 Sync 內(nèi)部類,這個內(nèi)部類又有兩個子類,一個 FairSync 和一個 NonfairSync,分別用來實現(xiàn)公平鎖和非公平鎖。而這個 Sync 內(nèi)部類,又是 AbstractQueuedSynchronizer 的子類。

      1. 我們 new ReentrantLock 的時候做了什么事?

      /**
       * Creates an instance of {@code ReentrantLock}.
       * This is equivalent to using {@code ReentrantLock(false)}.
       */
       public ReentrantLock() {
           sync = new NonfairSync();
       }

      通過這個構(gòu)造方法可以知道,實際上是構(gòu)建了一個非公平鎖。如果 new 的時候傳了 true,調(diào)用的構(gòu)造方法就是:

      /**
       * Creates an instance of {@code ReentrantLock} with the
       * given fairness policy.
       *
       * @param fair {@code trueif this lock should use a fair ordering policy
       */
       public ReentrantLock(boolean fair) {
           sync = fair ? new FairSync() : new NonfairSync();
       }

      所以傳的是 true,構(gòu)建的就是公平鎖。

      2. 公平和非公平有什么區(qū)別?

      非公平鎖源碼:

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

      公平鎖源碼:

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

      乍一看兩段代碼好像沒啥不一樣,其實不同之處在,if (c == 0)這段判斷中。公平鎖多了一個判斷條件,即!hasQueuedPredecessors(),看看這個方法的源碼:

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

      這個方法也很簡單,首先是頭節(jié)點不等于尾節(jié)點,然后就是頭節(jié)點的下一個節(jié)點為空或者頭節(jié)點的下一個節(jié)點保存的 Thread 不等于當(dāng)前的 Thread。簡單地說就是看隊列中有沒有除了當(dāng)前 Thread 以為的 Thread 在等待獲取鎖,有就返回 true,否則返回 false。所以公平鎖就是多了這個判斷,其他都一樣。

      下一篇文章將會從源碼層面分析 ReentrantLock 的加鎖過程,敬請期待!


      掃描二維碼

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多