JVM對Java的原生鎖做了哪些最佳化?在Java之前,Monitor的實現完全依賴底層作業系統的互斥鎖來實現,也就是我們剛才在問題二中所聞述的獲取/釋放鎖的邏輯。
由於Java層面的執行緒與作業系統的原生執行緒有對映關係,如果要將一個執行緒進行阻塞或喚起都需要作業系統的協助,這就需要從使用者態切換到核心態來執行,這種切換代價十分昂貴,很耗處理器時間,現代JDK中做了大量的最佳化。一種最佳化是使用自旋鎖,即在把執行緒進行阻塞操作之前先讓執行緒自旋等待一段時間,可能在等待期間其他執行緒已經解鎖,這時就無再讓執行緒執行阻塞操作,避免了使用者態到核心態的切換。
再讓執行緒執行阻塞操作,避免了使用者態到核心態的切換。
現代JDK中還提供了三種不同的 Monitor實現,也就是三種不同的鎖:
偏向鎖( Biased Locking)
輕量級鎖
重量級鎖
這三種鎖使得JDK得以最佳化Synchronized的執行,當JM檢測到不同的競爭狀況時,會自動切換到適合的鎖實現,這就是鎖的升級、降級。
當沒有競爭出現時,預設會使用偏向鎖。
JVM會利用CAS操作,在物件頭上的Mark Word部分設定執行緒ID,以表示這個物件偏向於當前執行緒,所以並不涉及真正的互斥鎖,因為在很多應用場景中,大部分物件生命週期中最多會被一個執行緒鎖定,使用偏斜鎖可以降低無競爭開銷。
如果有另一執行緒試圖鎖定某個被偏斜過的物件,JM就撤銷偏斜鎖,切換到輕量級鎖實現。
輕量級鎖依賴CAS操作Mark Word來試圖獲取鎖,如果重試成功,就使用普通的輕量級鎖;否則,進一步升級為重量級鎖。
課程推薦:
最新評論