[英]Is object initialization atomic in Java?
我知道myObject1 = myObject2
是原子的,但是下面的代碼行是原子的嗎?
Object obj1 = new Object();
它實際上可以在初始化引用的中間暫停嗎?
它不是原子的。 沒有什么能阻止你在 Object 構造函數中sleep
,或者無限循環,或者在構造函數中拋出異常。
注意:盡管可能,但這些都是反模式,不推薦使用。
這條線不是原子的。 發生了兩件事:首先,創建了新的Object
(通常不是原子的),然后將這個 object 的引用分配給變量obj1
。 比如說,由Thread1
執行的行和Thread2
觀察變量的 state 。 Thread2
可以觀察到三種狀態(為簡單起見,假設 object 創建本身是原子的),
obj1 == null
,未創建 objectobj1 == null
, object 已創建,但對它的引用尚未分配給變量obj1 != null
,該行已完全執行原子性表明Thread2
可能僅觀察 state 1 和 3,但必須強制執行。 使其原子化的一種方法是通過同步(在此示例中, obj1
是 class 字段):
public synchronized Object getObj() {
if (obj1 == null)
obj1 = new Object();
return obj1;
}
第一個調用此方法的線程將初始化該字段,進一步調用將簡單地返回該變量。 由於互斥,創建null
后,線程不可能觀察到obj1
中的null,因為不同線程的方法調用不能重疊。
引用分配是原子的。 沒有條件可以部分分配引用本身(這顯然會導致 VM 有時崩潰)。 它將是 null 或不為空。 在分配引用之前 object 的構造不是原子的,但是在構造過程完成之前,您將無法訪問新的 object 以分配給引用。
有趣的是,參考分配可能發生在與主 memory 不同步的芯片上緩存的 memory 中。 這意味着其他線程不會立即看到分配。 有兩種方法可以確保將引用分配推送到主 memory 其他線程可以立即看到它。 (1) 將引用聲明為 volatile 並 (2) 將引用分配放在同步塊中(退出同步塊會將緩存的引用提交到主內存)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.