Java数组:synchronized + Atomic *,还是同步的?

时间:2011-11-30 09:58:04

标签: java arrays atomic volatile synchronized

这个问题一再被问到,但我仍有疑问。当人们说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.

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

2 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:0)

如果我的理解是正确的,synchronized(total)会同步total的任何访问,因此也应该同步访问(读取和写入)数组中的值。< / p>

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