国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 查漏補缺synchronized和ReentrantLock的基本原理

查漏補缺synchronized和ReentrantLock的基本原理

2021-03-04 23:52今日頭條敲敲敲代碼 Java教程

synchronized基本原理是通過CPU指令實現的。ReentrantLock是通過AQS(AbstractQueuedSynchronizer)實現的。

查漏補缺synchronized和ReentrantLock的基本原理

 一、java鎖的類型

java的鎖有這么幾類。

樂觀鎖和悲觀鎖

  • 樂觀鎖就是JVM認為不通過加鎖也能保證并發的正確性。典型實現是諸如AtomicInteger的實現。
  • 悲觀鎖就是需要加鎖互斥。典型實現是Synchronized(Synchronized屬于樂觀鎖還是悲觀鎖其實跟具體實現有關,大部分場景下都是悲觀鎖)和ReentrantLock。

可重入和不可重入

  • 可重入是指當一個線程獲取了鎖,但是沒有釋放,這個線程又要獲取這個鎖,仍然能獲取成功。Synchronized和ReentrantLock都是可重入鎖。
  • 不可重入是可重入的否命題,這樣自己會把自己死鎖。應該沒有這樣的實現。

公平鎖和非公平鎖

  • 公平鎖是先請求鎖的線程肯定先獲得鎖,也就是FIFO。公平說是不是就是合理的?可能也不一定,因為這會造成上下文的切換。ReentrantLock默認是非公平鎖,但是可以通過構造方法構造公平鎖實例。
  • 非公平鎖是新來的線程有優先獲得鎖的機會,也就是可以插隊。合理嗎?可能也不合理,因為這可能造成“餓死”現象:在排隊的舊的線程總是獲取不到鎖。Sysnchronized其實就是非公平鎖。

排他鎖和共享鎖

  • 排他鎖是一個線程獲得鎖之后,其他線程不能再獲得鎖。大多數場景下都是排他鎖。
  • 共享鎖是指多個線程可以同時獲得鎖。常見的是多個線程可以同時獲得讀鎖。

二、synchronized

synchronized基本原理是通過CPU指令實現的。在jdk1.6之前是很重的鎖。因為java的多線程與操作系統的線程是一一對應的。當java線程阻塞的時候需要切換到內核態的線程進行阻塞,喚醒的時候又要從內核態切換到用戶態,進行了很重的上下文切換。那么能不能當一個線程獲取不到鎖的時候不阻塞呢?自旋可以嗎?這樣就有了synchronized的四種實現:無鎖、偏向鎖、輕量鎖、重量鎖。

synchronized鎖的是java的對象頭,再詳細點是mark word。

查漏補缺synchronized和ReentrantLock的基本原理

無鎖

這個沒有什么好說的。沒有將這個對象通過synchronized包括。

偏向鎖

當只有一個線程在訪問鎖的時候,會在mark word中通過CAS的方式設置當前線程的threadId。如果成功的話,加鎖成功(由于只有一個線程,肯定成功)。這樣當這個線程再次請求鎖的時候,看mark word的thread id和自己是否相同,如果相同加鎖成功。注意,它是沒有解鎖操作的。如果是另一個線程也來了,由于上一個線程沒有解鎖操作,這個新線程的CAS肯定失敗。這時當JVM沒有字節碼要執行的時候(全局安全點),會檢查上一個線程有沒有結束,如果結束,則通過CAS將mark word中的thread id字段更新為新線程的threadId。如果上一個線程沒有結束,這就存在并發了。偏向鎖無法完成使命,需要升級為輕量鎖。

輕量鎖

接著上面偏向鎖的上一個線程A和新的線程B的例子。JVM此時進行一下線程A對mark word的操作。將mark word拷貝到當前線程的棧空間中,CAS操作mark word的指針指向這個棧空間的地址,CAS操作當前線程的棧空間再加一個指向mark word的指針,這兩個操作成功后,其實第一個CAS成功就是成功,這樣線程A就獲得了鎖,升級成為了輕量鎖。線程B會自旋等待線程A的釋放。線程A怎么釋放鎖呢?只要將第一個CAS操作的指針(mark word指向線程棧的指針)釋放了就可以了,線程B自旋檢測mark word的指向,去搶占鎖。如果此時又來一個線程C呢?是不是也自旋?可以同時有幾個線程自旋?線程B能自旋多少次?這些都是有JVM參數可配置的。

查漏補缺synchronized和ReentrantLock的基本原理

重量鎖

這個其實也沒什么好說的。存在并發訪問時,直接將線程切換到內核態阻塞。

三、ReentrantLock

ReentrantLock是通過AQS(AbstractQueuedSynchronizer)實現的。需要解決的問題:

需要有個狀態表示這個lock對象是不是被搶占了,如果可重入的話,被這個線程搶占了多少次。這個狀態標識其實就是AQS的state成員變量。對state的操作肯定要線程安全。可以通過CAS解決。

protected final boolean tryAcquire(int acquires) { 

    final Thread current = Thread.currentThread(); 

    int c = getState(); 

    if (c == 0) { 

        // 這個是公平鎖的實現。需要判斷隊列中有沒有等待的線程, 

        // 如果沒有才進行CAS搶占     

        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

多個線程同時搶占lock,只有一個線程能成功,其他線程怎么排隊呢?排隊的線程怎么搶占鎖呢?這就用到了一個隊列。這個隊列的插入是通過自旋和CAS實現的。

private Node addWaiter(Node mode) { 

    Node node = new Node(mode); 

    // 循環嘗試 

    for (;;) { 

        Node oldTail = tail; 

        if (oldTail != null) { 

            // 無鎖修改前驅指針 

            node.setPrevRelaxed(oldTail); 

            // CAS修改tail 

            if (compareAndSetTail(oldTail, node)) { 

                // 修改后續指針 

                oldTail.next = node; 

                return node; 

            } 

        } else { 

            initializeSyncQueue(); 

        } 

    } 

排隊的線程搶占lock呢?

final boolean acquireQueued(final Node node, int arg) { 

    boolean interrupted = false

    try { 

        for (;;) { 

            final Node p = node.predecessor(); 

            // 如果前驅節點是頭節點,并且獲取鎖成功,直接返回。 

            // 但是大多數情況,可能運氣沒這么好 

            if (p == head && tryAcquire(arg)) { 

                setHead(node); 

                p.next = null; // help GC 

                return interrupted; 

            } 

            // 是否需要阻塞 

            if (shouldParkAfterFailedAcquire(p, node)) 

                // 這里阻塞 

                interrupted |= parkAndCheckInterrupt(); 

        } 

    } catch (Throwable t) { 

        cancelAcquire(node); 

        if (interrupted) 

            selfInterrupt(); 

        throw t; 

    } 

怎么喚醒上面阻塞的線程呢?這就要看下釋放邏輯。

public final boolean release(int arg) { 

    // 釋放lock 

    if (tryRelease(arg)) { 

        Node h = head; 

        if (h != null && h.waitStatus != 0) 

            unparkSuccessor(h);  // 喚醒頭結點的后續節點。注意頭結點是虛節點,沒有實在意義 

        return true

    } 

    return false

原文地址:https://www.toutiao.com/i6933840985927598600/

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 日韩视频―中文字幕 | 91尤物网站网红尤物福利 | 色综合天天综合网国产成人网 | 天天摸天天操 | 在线看片你懂得 | 欧美不卡视频 | 成年片 | 日韩视频精品在线 | 久久黄色 | 国产亚洲精品久久久闺蜜 | 日韩激情一区二区三区 | 免费毛片a线观看 | 久久大香 | 成人黄色片网站 | 日韩在线 中文字幕 | 天堂一区二区三区在线 | 国产精品成人一区二区三区夜夜夜 | 成年片| 精品一区二区三区成人精品 | 久久久久久久久久一区二区 | av成人毛片 | 91视频国产精品 | 不卡的一区二区 | 亚洲免费视频大全 | 日韩精品在线播放 | 欧美中文字幕一区二区 | 在线一区二区三区做爰视频网站 | 中文字幕亚洲欧美日韩在线不卡 | 九九综合| 欧美成人a∨高清免费观看 国产99久久 | 91精品久久久久 | 青草青草久热精品视频在线观看 | 中文字幕在线一区二区三区 | 成人精品视频一区二区三区 | 先锋影音av中文字幕 | 久久久99久久久国产自输拍 | 中国女人真人一级毛片 | 国产日韩欧美综合 | 亚洲一区在线免费观看 | 日韩精品视频在线 | 中文字幕一级 |