这个问题一再被问到,但我仍然有疑问。当人们说同步创建内存屏障时,这个内存屏障应用于什么,任何缓存变量?这看起来不太可行。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
。这是否发生?
谢谢,这真是我需要的答案。可惜这是我的第一个问题,所以我还没有投票。 –
当你提到“*不相关的* ones”时,你的意思是**在synchronized块中的变量(但与* total *无关),对吧?即你并不是指与全局无关的那些(即与* total *无关并且与* total *用于同步,但被缓存并且在主存储器中具有过时值的块)无关。换句话说,你并不是指整个过程的所有缓存变量? (我知道这可能是一个愚蠢的问题,但只是为了确保......)。 –
synchronized使用一个内存屏障来确保所有内存处于该线程的一致状态,无论该内存是否在该块内被引用。 –