Java-массивы: синхронизированные + атомарные * или синхронизированные достаточно? - PullRequest
4 голосов
/ 30 ноября 2011

Этот вопрос задавался снова и снова, но у меня все еще есть сомнения. Когда люди говорят, что 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.

Интересно, можно ли просто заменить тип итога простым двойным []: для этого потребуется, чтобы synchronized (total) (в методе run ()) гарантировал, что я не работаю с локальными копиями Индекс в массиве double, то есть ограничение памяти применяется не только к значению total (которое находится под указателем), но и к индексам total. Это происходит?

Ответы [ 2 ]

5 голосов
/ 30 ноября 2011

Барьер памяти применяется ко всем ссылкам памяти, даже не связанным.Когда вы синхронизируете total, вы увидите актуальную копию любых значений памяти, а когда вы покинете блок, возникает еще один барьер памяти.

0 голосов
/ 30 ноября 2011

Если мое понимание правильное synchronized(total) будет синхронизировать любой доступ к total и, следовательно, должен синхронизировать доступ (чтение и запись) к значениям в массиве тоже.Поскольку массив double напрямую содержит значения вместо ссылок, они не должны быть доступны другим потокам во время выполнения синхронизированного блока.Если бы у вас был массив объектов, вы бы не смогли изменить ссылки в массиве, но вы все равно могли бы получить доступ к самим объектам.

...