當多個線程同時競爭一個對象監視器時:當前對象結構中的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加類鎖時,會有嚴重的效率問題,此時須要考慮是否能夠修改成細粒度鎖,當修改細粒度鎖時,要避免死鎖。
上述如有不對,麻煩各位指正