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