java併發編程(七)synchronized原理之重量級鎖 一、何爲鎖膨脹? 二、自適應自旋鎖

前文講解輕量級鎖時,當線程使用CAS嘗試對對象加鎖,有兩種失敗情況,一種情況是自己執行了synchronized鎖重入;另外一種,就是本文需要學習的重點內容:鎖膨脹

一、何爲鎖膨脹?

輕量級鎖是指在滿足一定的條件內,使用CAS(自旋)來嘗試獲取對象鎖的一種機制,如果超過以下條件,則會膨脹爲重量級鎖:

1)在jdk1.6前,默認10次,可通過-XX:PreBlockSpin來修改,或者自旋線程數超過CPU核數的一半。

2)jdk1.6之後,引入了自適應自旋鎖,次數並非一成不變。根據獲取鎖的成功率來決定是否能有更長的等待時間。

假設當前Object對象,已經被Thread1所持有,當Thread2前來競爭這把鎖,滿足上述條件後,會發生鎖膨脹,如下圖所示:

如上所示,此時Thread2來獲取輕量級鎖肯定失敗的,所以會進入鎖膨脹的流程:

1)爲Object對象申請Monitor鎖,Object的Mark Word指向Monitor地址;Monitor的Owner指向Thread1的鎖記錄。

2)Thread2進入Monitor的EntryList當中,狀態變成BLOCKED。

當Thread1執行完代碼塊的內容後,開始釋放鎖,使用CAS去重置Object的Mark Word,此時會失敗。因爲當前對象頭存儲的是Monitor的地址。

所示此時會進入重量級鎖的解鎖過程。將Monitor的Owner設置爲null,同時喚醒EntryList中的Thread-2。

二、自適應自旋鎖

jdk1.6之後,引入了自適應自旋鎖,在重量級鎖當中,也進行了一些優化。

前面提到當發生鎖膨脹後,沒持有鎖的線程會進入Monitor的EntryList當中進行阻塞,實際情況是,會通過自適應自旋鎖進行一定次數的自旋,如果獲取到鎖了,就避免進入阻塞狀態(會進行上下文切換)。如果沒獲取到鎖,此時在進入阻塞狀態。

  • 自旋是佔用CPU的,只有在多核CPU中才能發揮優勢。
  • 自適應自旋鎖會動態調整自旋次數,獲取鎖成功的次數多,就會多自旋幾次;如果一次都沒有成功,則會可能會直接進行阻塞。
  • java7後不能控制是否開啓自旋鎖。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章