2011-11-30 26 views
3

這個問題一再被問到,但我仍然有疑問。當人們說同步創建內存屏障時,這個內存屏障應用於什麼,任何緩存變量?這看起來不太可行。Java數組:同步+原子*,或同步足夠?

因此,由於這個疑問,我已經寫了一些代碼,看起來像這樣:

final AtomicReferenceArray<Double> total=new AtomicReferenceArray<Double>(func.outDim); 
for(int i=0; i<func.outDim; i++) total.set(i, 0.); 
for(int i=0; i<threads; i++){ 
    workers[i]=new Thread(new Runnable(){ 
     public void run() { 
      double[] myPartialSum=new double(func.outDim); 
      //some lengthy math which fills myPartialSum... 

      //The Atomic* guarantees that I'm not writing local copies of the Double references (whose value are immutables, so it's like an array of truly volatile doubles) in variable total, synchronized(total) atomizes the sum 
      synchronized(total){ for(int i=0; i<func.outDim; i++) total.set(i, total.get(i)+myPartialSum[i]); } 
     }; 
    workers[i].start(); 
} 
//wait for workers to terminate... 

//print results accessing total outside of a synchronized(total) block, since no worker is alive at this point. 

我不知道是否有可能剛剛替補總的類型有普通的雙[]:這將需要同步(總)(在run()方法中)確保我沒有使用雙精度數組中每個索引的本地副本,也就是說,內存圍欄不僅適用於total本身的值在引擎蓋下是一個指針),但也指向total。這是否發生?

回答

4

內存屏障適用於所有內存引用,甚至不相關的內存引用。當您同步total時,您將看到任何內存值的最新副本,而當您離開該塊時,還有另一個內存障礙。

+0

謝謝,這真是我需要的答案。可惜這是我的第一個問題,所以我還沒有投票。 –

+0

當你提到「*不相關的* ones」時,你的意思是**在synchronized塊中的變量(但與* total *無關),對吧?即你並不是指與全局無關的那些(即與* total *無關並且與* total *用於同步​​,但被緩存並且在主存儲器中具有過時值的塊)無關。換句話說,你並不是指整個過程的所有緩存變量? (我知道這可能是一個愚蠢的問題,但只是爲了確保......)。 –

+1

synchronized使用一個內存屏障來確保所有內存處於該線程的一致狀態,無論該內存是否在該塊內被引用。 –

0

如果我的理解是正確的synchronized(total)將同步任何訪問total,因此應同步訪問(讀取和寫入)的值在數組中了。

由於double數組直接包含值而不是引用,因此在執行同步塊期間,其他線程不應該可以訪問這些值。如果您有一個對象數組,您將無法更改數組中的引用,但仍然可以訪問這些對象本身。

+0

問題是我需要互斥和最新值(和引用)。在你的回答中,你似乎只考慮了第一件事。 –