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加類鎖時,會有嚴重的效率問題,此時需要考慮是否可以修改為細粒度鎖,當修改細粒度鎖時,要避免死鎖。

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM