輕量級鎖究竟是怎麼回事啊啊啊啊

微信公衆號:IT一刻鐘。大型現實非嚴肅主義現場,一刻鐘與你分享優質技術架構與見聞,作一個有劇情的程序員。關注可第一時間瞭解更多精彩內容,按期有福利相送喲。程序員

以前咱們講了synchronized的原理,以及其中的偏向鎖,送佛送到西,此次咱們來講一說輕量級鎖吧。安全

友情提醒:上面兩篇沒有看過的看官,請先閱讀上面兩篇以後,再讀此篇,這樣效果會更佳哦~微信

開局一張圖。架構

看一張大圖

 

流程講解

當JVM關閉了偏向鎖模式,對象在建立的時候,Mark Word中存儲的是hash值,年代,是否偏向鎖標誌位爲0,標誌位是01。即一個無鎖不可偏向狀態。學習

輕量級鎖邏輯spa

1.當線程訪問同步塊,先判斷鎖狀態標誌位,若是是00,則說明是輕量級鎖,JVM會先在當前線程棧幀中分配Lock Record空間;.net

2.將鎖對象頭中的Mark Word拷貝到當前線程的Lock Record中,稱爲Displaced Mark Word,而後使用CAS,將對象頭中的Mark Word修改成指向當前線程棧中Lock Record的指針(如圖)。若是成功,則獲取輕量級鎖,執行同步塊中的代碼,若是失敗,則進行自旋競爭鎖,自旋達到必定的次數若是依舊沒有獲取到鎖,則升級爲重量級鎖(由於自旋會消耗CPU,爲了不無用的自旋,一旦鎖升級爲重量級鎖,就不會恢復到輕量級鎖,自旋的線程會被掛起阻塞住);線程

CAS操做以前堆棧與對象的狀態3d

 

CAS操做以後堆棧與對象的狀態指針

3.執行完同步代碼塊代碼,退出同步代碼塊,使用CAS開始輕量級鎖解鎖,解鎖的條件須要知足如下兩個:

    1)對象頭Mark Word中鎖記錄指針是否依舊指向當前線程Lock Record

    2)拷貝在當前線程Lock Record的Mark Word信息是否與對象頭中的Mark Word一致

4.若是知足,則成功釋放鎖;

5.若是不知足,則釋放鎖,喚醒被掛起阻塞的線程,開始重量級鎖的競爭。

注:當超過自旋閾值,競爭的線程就會把鎖對象Mark Word指向重量級鎖,致使Mark Word中的值發生了變化,當原持有輕量級鎖的線程執行完畢,嘗試經過CAS釋放鎖時,由於Mark Word已經指向重鎖,再也不是指向當前線程Lock Record的指針,因而解鎖失敗,這時原持有輕量級鎖的線程就會知道鎖已經升級爲重量級鎖。

偏向鎖升級爲輕量級鎖

1.先在原持有偏向鎖的線程棧幀中分配Lock Record;

2.將對象頭Mark Word拷貝到原持有偏向鎖的線程Lock Record中,而後使用CAS,將對象頭中的Mark Word修改成指向當前線程棧中Lock Record的指針。將原持有偏向鎖的線程升級爲持有偏向鎖的線程;

3.喚醒線程,從安全點繼續執行,執行完畢解鎖。

輕量級鎖的重入計數

咱們看個demo,在該demo中重複3次得到鎖,

synchronized(obj){
    synchronized(obj){
        synchronized(obj){
        }
    }
}

假設鎖的狀態是輕量級鎖,如圖反應了Mark Word和線程棧中Lock Record的關係,右邊線程棧中包含3個指向當前鎖對象的Lock Record。其中棧中最高位的Lock Record爲第一次獲取鎖時分配的,其中Displaced Mark word爲鎖對象加鎖前的Mark Word,而以後的鎖重入,則會在線程棧中分配一個Displaced Mark word爲null的Lock Record,用來重入計數。

 

每次釋放鎖的時候則會刪除對應的Lock Record。 這就是輕量級鎖的實現邏輯,相對於偏向鎖來講,邏輯會稍微簡單一些。

若是以爲學習到了,歡迎轉發加關注,那是我分享的動力呀~

 

相關文章
相關標籤/搜索