Java数组:synchronized + Atomic*,或者synchronized就足够了



这个问题已经被问了一遍又一遍,但我仍然有一个疑问。当人们说同步创建了一个内存屏障,这个内存屏障适用于什么,任何缓存变量吗?这看起来不可行。

所以,由于这个疑问,我写了一些代码,看起来像这样:
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.

我想知道是否有可能用普通的双精度[]替换total的类型:这将要求synchronized(total)(在run()方法中)确保我不使用双精度数组中每个索引的本地副本,也就是说,内存围栏不仅适用于total本身的值(这是一个指针),而且也适用于total的索引。这种情况会发生吗?

内存屏障适用于所有内存引用,甚至是不相关的引用。当您同步total时,您将看到任何内存值的最新副本,当您离开块时,存在另一个内存屏障。

如果我的理解是正确的,synchronized(total)将同步total的任何访问,因此应该同步访问(读和写)到数组中的值。

由于double数组直接包含值而不是引用,因此在执行同步块期间,这些值不应该被其他线程访问。如果你有一个对象数组,你将不能改变数组中的引用,但你仍然可以访问对象本身。

相关内容

最新更新