<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### 如何解鎖 我們已經剖析了加鎖過程中的基本流程,接下來再對解鎖的基本流程進行分析。由于ReentrantLock在解鎖的時候,并不區分公平鎖和非公平鎖,所以我們直接看解鎖的源碼: ~~~ // java.util.concurrent.locks.ReentrantLock public void unlock() { sync.release(1); } ~~~ 可以看到,本質釋放鎖的地方,是通過框架來完成的。 ~~~ // java.util.concurrent.locks.AbstractQueuedSynchronizer public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } ~~~ 在ReentrantLock里面的公平鎖和非公平鎖的父類Sync定義了可重入鎖的釋放鎖機制。 ~~~ // java.util.concurrent.locks.ReentrantLock.Sync // 方法返回當前鎖是不是沒有被線程持有 protected final boolean tryRelease(int releases) { // 減少可重入次數 int c = getState() - releases; // 當前線程不是持有鎖的線程,拋出異常 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // 如果持有線程全部釋放,將當前獨占鎖所有線程設置為null,并更新state if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } ~~~ 我們來解釋下述源碼: ~~~ // java.util.concurrent.locks.AbstractQueuedSynchronizer public final boolean release(int arg) { // 上邊自定義的tryRelease如果返回true,說明該鎖沒有被任何線程持有 if (tryRelease(arg)) { // 獲取頭結點 Node h = head; // 頭結點不為空并且頭結點的waitStatus不是初始化節點情況,解除線程掛起狀態 if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } ~~~ 這里的判斷條件為什么是h != null && h.waitStatus != 0? > h == null Head還沒初始化。初始情況下,head == null,第一個節點入隊,Head會被初始化一個虛擬節點。所以說,這里如果還沒來得及入隊,就會出現head == null 的情況。 > > h != null && waitStatus == 0 表明后繼節點對應的線程仍在運行中,不需要喚醒。 > > h != null && waitStatus < 0 表明后繼節點可能被阻塞了,需要喚醒。 再看一下unparkSuccessor方法: ~~~ // java.util.concurrent.locks.AbstractQueuedSynchronizer private void unparkSuccessor(Node node) { // 獲取頭結點waitStatus int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); // 獲取當前節點的下一個節點 Node s = node.next; // 如果下個節點是null或者下個節點被cancelled,就找到隊列最開始的非cancelled的節點 if (s == null || s.waitStatus > 0) { s = null; // 就從尾部節點開始找,到隊首,找到隊列第一個waitStatus<0的節點。 for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 如果當前節點的下個節點不為空,而且狀態<=0,就把當前節點unpark if (s != null) LockSupport.unpark(s.thread); } ~~~ 為什么要從后往前找第一個非Cancelled的節點呢?原因如下。 之前的addWaiter方法: ~~~ // java.util.concurrent.locks.AbstractQueuedSynchronizer private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; } ~~~ 我們從這里可以看到,節點入隊并不是原子操作,也就是說,node.prev = pred; compareAndSetTail(pred, node) 這兩個地方可以看作Tail入隊的原子操作,但是此時pred.next = node;還沒執行,如果這個時候執行了unparkSuccessor方法,就沒辦法從前往后找了,所以需要從后往前找。還有一點原因,在產生CANCELLED狀態節點的時候,先斷開的是Next指針,Prev指針并未斷開,因此也是必須要從后往前遍歷才能夠遍歷完全部的Node。 綜上所述,如果是從前往后找,由于極端情況下入隊的非原子操作和CANCELLED節點產生過程中斷開Next指針的操作,可能會導致無法遍歷所有的節點。所以,喚醒對應的線程后,對應的線程就會繼續往下執行。繼續執行acquireQueued方法以后,中斷如何處理?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看