免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

JDK里的自旋鎖怎么用

這篇文章主要為大家展示了“JDK里的自旋鎖怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“JDK里的自旋鎖怎么用”這篇文章吧。

我們提供的服務有:網站建設、做網站、微信公眾號開發、網站優化、網站認證、中陽ssl等。為數千家企事業單位解決了網站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的中陽網站制作公司

自旋鎖是采用讓當前線程不停地的在循環體內執行實現的,當循環的條件被其他線程改變時才能進入臨界區。

JDK里面自旋鎖的實現有 SynchronousQueue  和 LinkedTransferQueue。  

先說公平鎖,先等待的線程先獲得數據。SynchronousQueue的內部類TransferQueue實現了公平鎖。

某一時刻 線程A看到內存的情況如下:   鏈表,head 和 tail 分別指向鏈首和鏈尾,并且線程執行了ht = tail 。

*
*  head            ht=tail
*    |               |
*    v               v*    M ->  U -> U -> U*

M 代表match , 表示該節點已經匹配到了數據,  poll 等到了 offer ,或者 offer 等到了 poll 。

U 代表unmatch , 表示該節點在等待填充數據或者數據等待poll 。

由于并發操作,經過其他線程的操作使得鏈表變成如下:(此操作是瞬間完成的)

*   head            ht      tail
*    |              |         |
*    v              v         v
*    M -> M -> U -> U -> U -> U*

有兩個U節點添加進來, 第二個節點M匹配到了數據。

假設此時線程A想再往鏈表添加U節點:

那么需要進行那些操作?

1: 發現ht != tail , 于是需要繼續循環

2:在 ht == tail 的情況下需要先 判斷 tail.next 是否為null , 如果不是則繼續循環

3:新建一個node,將 tail.next 指向新node。

4:將U賦值給tail 。    (如果只執行了3而還沒有執行4,就會出現2中的情況,ht=tail,但是ht.next 為空,說明此時有線程執行了3操作但是還沒有執行4操作,此時只需要繼續循環即可)

*  head           ht=tail*    |              |*    v              v*    U -> U -> U -> U -> U
/* *   head                tail *    |                   | *    v                   v
 *    U -> U -> U -> U -> U
 * */

5:  自旋等待match。

6: 等待結束有兩種可能結果: 6.1 超時取消    6.2 成功  

成功時: 因此只需將 head 指向node.next . 并且將 node.next 置空。 雖然此時   M -> M  但是只要其它線程正確的執行了M.next = null 即可。

/* *                  head                    tail *                   |                        | *                   v                        v
 *    M  M  M  M  M  M -> M -> U -> U - > U ->U
 * *//*
 *                           head          tail
 *                            |              |
 *                            v              v
 *    M  M  M  M  M  M ->  M  U -> U - > U ->U
 *
 */

等待超時:此時U按理也應該來到了鏈首,前面node的也都超時了,但萬一其他的線程沒有獲得cpu呢,就會出現如下的狀況,需要將U前面的幾個node也順便清理掉

/* *                  head                    tail *                   |                        | *                   v                        v *    M  M  M  M  M  U -> U -> U -> U - > U ->U * */

假設此時線程A是想將U變成M,這個邏輯很簡單,按順序找到一個U,嘗試給U的item賦值。成功結束,不成功繼續循環。

E transfer(E e, boolean timed, long nanos) {    QNode s = null; // constructed/reused as needed    boolean isData = (e != null);    for (;;) {
        QNode t = tail;        QNode h = head;        if (t == null || h == null)         // saw uninitialized value            continue;                       // spin        if (h == t || t.isData == isData) { // empty or same-mode            QNode tn = t.next;            if (t != tail)                  // inconsistent read                continue;            if (tn != null) {               // lagging tail                advanceTail(t, tn);                continue;            }if (timed && nanos <= 0)        // can't wait                return null;            if (s == null)
                s = new QNode(e, isData);            if (!t.casNext(null, s))        // failed to link in                continue;            advanceTail(t, s);              // swing tail and wait            Object x = awaitFulfill(s, e, timed, nanos);            if (x == s) {                   // wait was cancelled                clean(t, s);                return null;            }if (!s.isOffList()) {           // not already unlinked                advanceHead(t, s);          // unlink if head                if (x != null)              // and forget fields                    s.item = s;                s.waiter = null;            }return (x != null) ? (E)x : e;        } else {                            // complementary-mode            QNode m = h.next;               // node to fulfill            if (t != tail || m == null || h != head)continue;                   // inconsistent read            Object x = m.item;            if (isData == (x != null) ||    // m already fulfilled                x == m ||                   // m cancelled                !m.casItem(x, e)) {         // lost CAS                advanceHead(h, m);          // dequeue and retry                continue;            }

            advanceHead(h, m);              // successfully fulfilled            LockSupport.unpark(m.waiter);            return (x != null) ? (E)x : e;        }
    }
}

自旋分析:

Object awaitFulfill(QNode s, E e, boolean timed, long nanos) {/* Same idea as TransferStack.awaitFulfill */    final long deadline = timed ? System.nanoTime() + nanos : 0L;    Thread w = Thread.currentThread();    int spins = ((head.next == s) ?
                 (timed ? maxTimedSpins : maxUntimedSpins) : 0);    for (;;) {if (w.isInterrupted())
            s.tryCancel(e);        Object x = s.item;        if (x != e)return x;        if (timed) {
            nanos = deadline - System.nanoTime();            if (nanos <= 0L) {
                s.tryCancel(e);                continue;            }
        }if (spins > 0)
            --spins;        else if (s.waiter == null)
            s.waiter = w;        else if (!timed)
            LockSupport.park(this);        else if (nanos > spinForTimeoutThreshold)
            LockSupport.parkNanos(this, nanos);    }
}

循環判斷 node.item 有沒有變化,如果有變化則匹配成功,如果沒有則繼續循環, 循環一定的次數(spins)后還沒有匹配成功則使用 LockSupport.park() 來阻塞線程。這個循環過程即可稱為自旋。

但是公平鎖存在一個問題:

/* * *  head            ht=tail *    |               | *    v               v *    M ->  U -> U -> U *   
 *   | *   | *  U變成M,但是此線程并沒有獲得cpu,沒法立即執行,于是后面獲得cpu的線程便有了意見,為啥不將數據給我,我能立即執行。 */

要想解決此問題說來也十分簡單,每個線程只需不停的將自己的node和head進行交換(casHead)即可優先獲得task。 這個是在 TransferStack中實現的,說起來簡單,但實現起來則困難得多。其實這也是經常聽到的搶占式執行吧,SynchronousQueue 默認使用非公平鎖。

public SynchronousQueue() {this(false);}public SynchronousQueue(boolean fair) {transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();}

以上是“JDK里的自旋鎖怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注創新互聯行業資訊頻道!

文章名稱:JDK里的自旋鎖怎么用
鏈接URL:http://m.newbst.com/article18/jocogp.html

成都網站建設公司_創新互聯,為您提供服務器托管、自適應網站網頁設計公司、網站營銷、Google外貿建站

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

手機網站建設