簡體   English   中英

JVM是否為每個對象創建一個互斥鎖以實現'synchronized'關鍵字?如果沒有,怎么樣?

[英]Does the JVM create a mutex for every object in order to implement the 'synchronized' keyword? If not, how?

作為一個越來越熟悉Java的C ++程序員,看到語言級別支持鎖定任意對象而沒有任何聲明對象支持這種鎖定,這有點奇怪。 為每個對象創建互斥鎖似乎是一個自動選擇的高成本。 除了內存使用,互斥體在某些平台上是OS有限的資源。 如果互斥鎖不可用但你的性能特征明顯不同,你可以旋轉鎖定,我希望這會損害可預測性。

在所有情況下,JVM是否足夠智能以識別特定對象永遠不會成為synchronized關鍵字的目標,從而避免創建互斥鎖? 可以懶惰地創建互斥鎖,但是這會引發自舉需要互斥鎖的自舉問題,即使解決了這個問題,我也認為仍然需要一些開銷來跟蹤是否已經創建了互斥鎖。 所以我假設如果這樣的優化是可能的,它必須在編譯時或啟動時完成。 在C ++中,由於編譯模型這樣的優化是不可能的(你不知道對象的鎖是否會跨庫邊界使用),但我對Java的編譯和鏈接知道不夠了解如果適用相同的限制。

作為一個看過某些JVM實現鎖的方式的人說的話......

通常的方法是從對象的標題字中的幾個保留位開始。 如果對象永遠不會被鎖定,或者它被鎖定但沒有爭用它會保持這種狀態。 如果在鎖定對象上發生爭用,JVM 會將鎖定膨脹為完整的互斥鎖數據結構,並且在對象的生命周期內保持這種狀態。

編輯 - 我剛剛注意到OP正在談論操作系統支持的互斥鎖。 在我看過的例子中,未充氣的互斥體是使用CAS指令等直接實現的,而不是使用pthread庫函數等。

你永遠不能確定一個對象永遠不會被用作鎖(考慮反射)。 通常,每個對象都有一個標題,其中一些位專用於鎖。 可以實現它,以便只根據需要添加標頭,但這有點復雜,你可能還需要一些標頭(類(相當於“vtbl”和C ++中的分配大小),哈希代碼和垃圾收集) 。

這是一個關於OpenJDK中同步實現的維基頁面。

(在我看來,為每個對象添加鎖是一個錯誤。)

這實際上是JVM的實現細節,不同的JVM可能以不同的方式實現它。 但是,它肯定不是可以在編譯時優化的東西,因為Java在運行時鏈接,並且這可能使以前未知的代碼保持在舊代碼中創建的對象並開始在其上進行同步。

請注意,在Java術語中,同步原語稱為“監視器”而不是互斥,並且它由特殊字節碼操作支持。 有一個比較詳細的解釋在這里

JVM不能直接使用比較和交換指令嗎? 假設每個對象都有一個字段lockingThreadId用於存儲鎖定它的線程的id,

while( compare_and_swap (obj.lockingThreadId, null, thisThreadId) != thisTheadId )
    // failed, someone else got it
    mark this thread as waiting on obj.
    shelf this thead

//out of loop. now this thread locked the object

do the work

obj.lockingThreadId = null;
wake up threads waiting on the obj

這是一個玩具模型,但它似乎並不太昂貴,並且不依賴於操作系統。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM