1. 程式人生 > >synchronized的幾種鎖和實現原理

synchronized的幾種鎖和實現原理

物件在堆中的結構


物件頭包括兩個部分,第一部分用於儲存自身執行時的資料例如GC標誌位、雜湊碼、鎖狀態等資訊。第二部分存放指向方法區類靜態資料的指標。

例項變數存放類的屬性資料資訊,包括父類的屬性資訊。如果是陣列的例項部分還包括陣列的長度。這部分記憶體按4位元組對齊。

填充資料區域的存在是因為虛擬機器要求物件起始地址必須是8位元組的整數倍。填充資料不是必須存在的,僅僅是為了位元組對齊。HotSpot VM的自動記憶體管理要求物件起始地址必須是8位元組的整數倍。物件頭本身是8的倍數,當物件的例項變數資料不是8的倍數,便需要填充資料來保證8位元組的對齊。另外,堆上物件記憶體的分配是併發進行的.

物件頭中的大致資訊如下

其中tag的兩個位元組用來顯示鎖的型別。通常我們說synchronized的物件鎖,就是這裡Tag=10時的monitor物件,這裡的Monitor address就是這個monitor物件(就是重量鎖)的地址。

新請求的執行緒會先被加到一個執行緒排隊佇列中,當某個持有鎖的執行緒unlock後,則排隊的執行緒競爭鎖。當執行執行緒的wait()方法後,執行緒釋放鎖,並進入wait執行緒集合,當呼叫notify()或notifyAll()後,執行緒重新進入排隊佇列。

synchronized中的鎖一般分為重量鎖(物件鎖),自旋鎖,自適應自旋鎖,輕量鎖,偏向鎖

使用synchronized關鍵字的程式碼塊在加鎖時,不會直接就加重量鎖,因為重量鎖對系統的開銷最大。若一個執行緒等待獲取鎖物件所持續的時間非常短,這時適合使用自旋鎖。所謂自旋鎖,就是等待鎖的執行緒並不進入阻塞狀態,而是執行一個無意義的迴圈。在迴圈結束後檢視鎖是否已經被釋放,若已經釋放則直接進入執行狀態。因為長時間無意義迴圈也會大量浪費系統資源,因此自旋鎖適用於間隔時間短的加鎖場景。

自適應自旋鎖:系統根據執行時的統計資訊,來調整自旋的次數。

輕量鎖和偏向鎖適用於沒有執行緒競爭的情況。無法代替重量鎖

參考資料點選這裡