考慮兩個線程:線程A和線程B。 (例如,讓ThreadA中是UI線程,並讓threadB一個自己的Thread
子類。)關於的數據可視性,是安全的在實例化一個類的ThreadA,它傳遞給構造threadB ,然後從專門使用它threadB?讓我用代碼澄清這一點。 (請注意,代碼被簡化,所以這種架構是有道理的,在其實際形式的實際應用。)實例化一個類,然後在另一個線程中使用它
public class SomeClass {
public SomeClass(....) {
// initialization
}
}
public class MyCustomThread extends Thread {
public MyCustomThread(SomeClass someClass) {
mSomeClass = someClass;
}
@Override
public void run() {
// operate on mSomeClass
}
}
而這一切開始的方法如下(其位置是無關緊要的)。這被稱爲threadA。
public void launchThread() {
SomeClass someClass = new SomeClass();
MyCustomThread threadB = new MyCustomThread(someClass); // MyCustomThread is a subclass of Thread
threadB.start();
// After this point, threadA never accesses someClass,
// and only threadB is operating on it
}
我知道構造不允許同步,並且需要在它裏面沒有同步的代碼(因爲這參考 - 除非泄露出來 - 直到類是不提供給其他線程在其創建者線程中構造)。所以我的問題是關於數據可見性:是代碼安全的,前提是我沒有從訪問someClass
(及其任何參考數據),threadB.start()
被調用後線程A?
換句話說,threadB.run()
會看到最新版本的someClass
數據(例如字段,內部引用等)?我的猜測:自會有上threadB訪問someClass
首次someClass
後沒有外部變化,threadB必須看到正確的價值觀,因爲它不能從之前緩存副本。因此,由於上述原因,我不需要在threadB.run()
的同步塊中訪問someClass
。 (再次提醒,它保證的ThreadA不threadB啓動後訪問someClass
。)
ThreadA正在修改有問題的對象,然後啓動第二個線程:這裏只有一個執行順序。 ThreadA創建對象,可能會修改它,將其提供給ThreadB,可能會更多地修改它,然後B啓動。沒有任何上下文切換或任何類似的事件導致異常的地方。 – cklab
@LuxuryMode:我看到cklab已經回答了,但這裏有不同的單詞:if * someClass.foo =「bar」*在調用** * threadB.start()*之後調用**,右鍵,threadB可能會看到過時的副本。但在我的軟件中,確保* threadB.start()*被調用後* someClass *不會被觸及。 –
其實,我的偏執是因爲run()訪問由另一個線程創建的數據。由於threadB是一個不同的線程,它可能已經緩存了這些數據的副本。但是,由於這是第一次訪問這些數據,因此它無法緩存副本。 –