2012-07-04 72 views
0

考慮兩個線程:線程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。 (再次提醒,它保證的ThreadAthreadB啓動後訪問someClass。)

回答

2

如果你的意思是說,threadB.start()之後,例如,通過someClass簡稱將不再進行修改任何其他線程:是的,threadB.run()將會看到最新版本。

在這種情況下真的沒有可能發生的併發/競爭條件。一切都在順序發生,你只是有一些對象,這些對象我認爲可能會導致你稍微偏執:)。

+0

ThreadA正在修改有問題的對象,然後啓動第二個線程:這裏只有一個執行順序。 ThreadA創建對象,可能會修改它,將其提供給ThreadB,可能會更多地修改它,然後B啓動。沒有任何上下文切換或任何類似的事件導致異常的地方。 – cklab

+0

@LuxuryMode:我看到cklab已經回答了,但這裏有不同的單詞:if * someClass.foo =「bar」*在調用** * threadB.start()*之後調用**,右鍵,threadB可能會看到過時的副本。但在我的軟件中,確保* threadB.start()*被調用後* someClass *不會被觸及。 –

+0

其實,我的偏執是因爲run()訪問由另一個線程創建的數據。由於threadB是一個不同的線程,它可能已經緩存了這些數據的副本。但是,由於這是第一次訪問這些數據,因此它無法緩存副本。 –

相關問題