JVM鎖優化

自旋鎖和自適應自旋

自旋鎖是當多個線程並行訪問共享數據時,用忙循環讓後面請求鎖的線程處於等待狀態,當自旋多次後仍然獲取不到鎖,再用傳統的方式將線程掛起。
忙循環就是用循環讓線程等待,忙循環也叫自旋。
在Java6之後,如果有線程剛通過自旋獲得了鎖,並且線程正在運行,那麼JVM會認爲自旋獲取鎖的命中率高,其他線程的自旋次數可能會增多。如果某個鎖通過自旋獲得的次數少,JVM可能會省略掉自旋獲取鎖,直接掛起線程去等待鎖。

鎖消除

鎖消除是指JVM即時編譯器運行時,對一些代碼上要求同步,但是被檢測到不可能存在共享數據的競爭,那麼鎖會進行消除。
它判斷的依據是通過判斷一段代碼在堆上的所有數據不會逃逸,被其他線程訪問到,那麼認爲它是線程私有的,進行鎖消除。

鎖粗化

編寫代碼時,要求同步代碼塊的範圍越小越好。但是在某些情況下,例如在循環中調用StringBuffer#append方法,這會對一個對象反覆加鎖,如果出現這類情況,JVM會將鎖同步的範圍優化到整個操作的外面,讓程序加一次鎖就行了。

輕量級鎖和偏向鎖

輕量級鎖和偏向鎖都是通過對象頭信息中的鎖標誌位進行鎖優化。
在對象頭的Mark Word中,有兩個位是鎖標誌位。00表示未鎖定、01表示輕量級鎖定、10表示重量級鎖。

  • 輕量級鎖

    輕量級鎖是指在代碼執行到同步塊時,如果同步對象未鎖定,JVM會在當前線程的棧幀中創建一個鎖記錄,然後使用CAS將對象的Mark Word更新爲執行鎖記錄的指針,如果操作成功,表示線程獲得鎖,將鎖標誌位變爲00。如果失敗,首先判斷對象的Mark Word是否指向當前線程的棧幀,如果是,可以直接進入同步塊執行,否則說明鎖被其他線程佔有了。如果有兩條以上的線程爭用同一個鎖,那麼輕量級鎖就失效了,變爲重量級鎖10。

  • 偏向鎖

    偏向鎖是指鎖對象會偏向於第一個獲得它的線程,如果之後鎖對象不再被其他線程獲取,那麼持有偏向鎖的線程永遠不用再進行同步。當鎖對象第一次被線程獲取時,JVM將鎖標誌改爲01,並用CAS把獲取到鎖的線程ID記錄到對象的Mark Word中。如果CAS成功,持有偏向鎖的線程以後每次執行同步塊時,JVM都不會有任何同步操作。但是當有另外的線程嘗試獲取這個鎖時,偏向模式就結束了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章