synchronized底層實現

 一、鎖升級的過程

  當多個線程同時競爭一個對象監視器時:當前對象結構中的mark word中是不是當前線程id,若是是則當前線程得到偏向鎖多線程

若是不是,則經過CAS將當前線程id置換到mark word中,若是成功則得到偏向鎖,若是不成功則說明有競爭,升級爲輕量級鎖。併發

後續再經過CAS將線程的指針放到mark word中,若成功則得到鎖,不然升級爲自旋鎖。自旋鎖仍然爲輕量級鎖,不成功升級爲重量級鎖。佈局

 

  對象結構:在JVM中,對象在內存中的佈局分爲三塊區域:對象頭、實例數據和對齊填充優化

 

 

 mark word:存在於對象頭中,存儲對象的hashcode,鎖標識,分代年齡及GC標識等信息spa

 

 

 由上圖能夠看出,爲什麼偏向鎖是將線程id放入mark word,輕量級鎖爲什麼將鎖的指針放入mark word。線程

 

偏向鎖:指偏向於第一個訪問的線程,在運行過程當中,同步鎖沒有競爭,則會在這個線程的頭部加一個標誌位,標記爲偏向鎖,若是發生競爭則會升級爲輕量級鎖或者重量級鎖指針

 

自旋鎖:線程請求不到對象鎖時不會堵塞,只是本身循環一下等待對象鎖的釋放。由於線程的堵塞和喚醒很是消耗內存,因此自旋鎖能夠很好的優化這個問題。code

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

 

二、升級到重量級鎖後,如何運行

 

 

 當多線程競爭時,不知足的條件的線程會進入同步隊列,知足條件後進入同步代碼。在同步代碼中執行wait方法,釋放對象鎖,進入右側等待隊列,當喚醒時 還須要再次得到互斥鎖。blog

 

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

 

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

相關文章
相關標籤/搜索