3 回答

TA貢獻2041條經(jīng)驗 獲得超4個贊
您使用的方法是線程安全的。由于您沒有引用您正在談?wù)摰穆暶鳎虼宋覠o法直接解決它們。但是 Java 語言規(guī)范對此主題很清楚。
在第 17.5 節(jié)中,它描述了
final
字段還允許程序員在沒有同步的情況下實現(xiàn)線程安全的不可變對象。線程安全的不可變對象被所有線程視為不可變的,即使使用數(shù)據(jù)競爭在線程之間傳遞對不可變對象的引用也是如此。這可以提供安全保證,防止錯誤或惡意代碼濫用不可變類。必須正確使用 final 字段以提供不變性保證。當一個對象的構(gòu)造函數(shù)完成時,它被認為是完全初始化的。只有在對象完全初始化后才能看到對對象的引用的線程可以保證看到該對象的最終字段的正確初始化值。

TA貢獻1847條經(jīng)驗 獲得超7個贊
我不認為“熱心單身”這個名字是合理的。
類或接口 T 將在以下任何一項第一次出現(xiàn)之前立即初始化:
T
是一個類并T
創(chuàng)建了一個實例。由
static
聲明的方法T
被調(diào)用。一個
static
場宣布T
分配。阿
static
通過聲明字段T
的使用量和字段不是常量變量(§4.12.4)。
因此,初始化和實例化Singleton
將getInstance()
在第一次調(diào)用該方法時發(fā)生,或者,由于您創(chuàng)建了該字段public
,當該字段第一次被訪問時,以先到者為準。但不是更早。換句話說,這個初始化已經(jīng)和所有其他嘗試執(zhí)行延遲初始化的嘗試一樣懶惰。
此初始化的安全性由JLS §12.4.2, 詳細初始化程序給出
對于每個類或接口
C
,都有一個唯一的初始化鎖LC
。從C
到到的映射由LC
Java 虛擬機實現(xiàn)自行決定。初始化過程C
如下:
同步初始化鎖,
LC
, forC
。這涉及等待直到當前線程可以獲取LC
。如果
Class
對象 forC
指示C
其他線程正在進行初始化,則釋放LC
并阻塞當前線程,直到通知正在進行的初始化已完成,此時重復此步驟。如果
Class
對象 forC
指示C
當前線程正在進行初始化,那么這必須是一個遞歸的初始化請求。釋放LC
并正常完成。如果
Class
對象 forC
指示C
已經(jīng)初始化,則不需要進一步的操作。釋放LC
并正常完成。…
這是一個過程,對類的引用的每次解析都遵循,獲取類的唯一初始化鎖并在類已經(jīng)初始化或當前線程是執(zhí)行初始化的線程時釋放它。這個鎖保證了線程安全,不管這個字段是否已經(jīng)聲明final
,只要是在類初始化的時候?qū)懙摹?/p>
它仍然是實現(xiàn)單例的最有效方法的原因在同一章中給出:
當可以確定類的初始化已經(jīng)完成時,實現(xiàn)可以通過省略步驟 1 中的鎖獲取(并在步驟 4/5 中釋放)來優(yōu)化此過程,前提是,就內(nèi)存模型而言,一切都發(fā)生了-在獲取鎖時存在的排序之前,在執(zhí)行優(yōu)化時仍然存在。
由于每個類只初始化一次,然后與初始化時間相比,在這個初始化狀態(tài)下使用了很長時間,因此這種優(yōu)化具有非常高的影響,因此,自第一個 Java 版本以來,這是最先進的。但是,正如這篇筆記所說,優(yōu)化不能破壞線程安全

TA貢獻1831條經(jīng)驗 獲得超9個贊
即使我們final
從public static final Singleton instance = new Singleton ();
.
那是因為 JVM 保證在任何線程訪問靜態(tài)instance
變量之前創(chuàng)建實例。
添加回答
舉報