1. 程式人生 > >synchronized底層實現

synchronized底層實現

 1、鎖升級的過程

  當多個執行緒同時競爭一個物件監視器時:當前物件結構中的mark word中是否是當前執行緒id,如果是則當前執行緒獲得偏向鎖。

如果不是,則通過CAS將當前執行緒id置換到mark word中,如果成功則獲得偏向鎖,如果不成功則說明有競爭,升級為輕量級鎖。

後續再通過CAS將執行緒的指標放到mark word中,若成功則獲得鎖,否則升級為自旋鎖。自旋鎖仍然為輕量級鎖,不成功升級為重量級鎖。

 

  物件結構:在JVM中,物件在記憶體中的佈局分為三塊區域:物件頭、例項資料和對齊填充

 

 

 mark word:存在於物件頭中,儲存物件的hashcode,鎖標識,分代年齡及GC標識等資訊

 

 

 由上圖可以看出,為何偏向鎖是將執行緒id放入mark word,輕量級鎖為何將鎖的指標放入mark word。

 

偏向鎖:指偏向於第一個訪問的執行緒,在執行過程中,同步鎖沒有競爭,則會在這個執行緒的頭部加一個標誌位,標記為偏向鎖,如果發生競爭則會升級為輕量級鎖或者重量級鎖

 

自旋鎖:執行緒請求不到物件鎖時不會堵塞,只是自己迴圈一下等待物件鎖的釋放。因為執行緒的堵塞和喚醒非常消耗記憶體,所以自旋鎖可以很好的優化這個問題。

但它只適合等待時間比較短的,而且併發量不高的場景。

 

2、升級到重量級鎖後,如何執行

 

 

 當多執行緒競爭時,不滿足的條件的執行緒會進入同步佇列,滿足條件後進入同步程式碼。在同步程式碼中執行wait方法,釋放物件鎖,進入右側等待佇列,當喚醒時 還需要再次獲得互斥鎖。

 

synchronized結構:

  Contention List:競爭佇列,所有請求鎖的執行緒首先被放在這個競爭佇列中;

  Entry List:Contention List中那些有資格成為候選資源的執行緒被移動到Entry List中;

   Wait Set:哪些呼叫wait方法被阻塞的執行緒被放置在這裡;

   OnDeck:任意時刻,最多隻有一個執行緒正在競爭鎖資源,該執行緒被成為OnDeck;

  Owner:當前已經獲取到所資源的執行緒被稱為Owner;

  大量併發執行緒會在contention List中,然後將有資格成為候選的放到entry list中。呼叫的wait的執行緒放到wait set中,當被喚醒後會放到entry list中。

指定EntryList中的某個執行緒為OnDeck執行緒(一般是最先進去的那個執行緒),然後onedeck執行緒去競爭鎖,但是此時其他未進入contention list的執行緒會先自旋一下看是否能獲得到鎖,

所以說synchronied不是公平的。

 當使用synchronized加類鎖時,會有嚴重的效率問題,此時需要考慮是否可以修改為細粒度鎖,當修改細粒度鎖時,要避免死鎖。

 

上述若有不對,麻煩各位指正

&n