4

This question has been asked again and again, but I have still a doubt. When people say that synchronized creates a memory barrier, what does this memory barrier apply to, ANY cached variable? This doesn't look like feasible.

So, due to this doubt, I have written some code that looks like this:

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.

I wonder if it's possible to just substitute the type of total with a plain double[]: this would require that synchronized(total) (in the run() method) assures that I'm not working with local copies of each index in the array of doubles, that is, the memory fence does not apply only to the value of total itself (which is under the hood a pointer), but to the indexes of total too. Does this happen?

Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65

2 Answers2

5

The memory barrier applies to all memory references, even unrelated ones. When you synchronize total you will see an up to date copy of any memory values and when you leave the block, there is another memory barrier.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks, that's excatly the answer I needed. Pity that this is my first question so I can't vote yet. – Lorenzo Pistone Nov 30 '11 at 10:46
  • When you mention "*unrelated* ones", do you mean the variables that are **inside** the synchronized block (but are not related to *total* structurally), right? I.e. you didn't mean the "globally" unrelated ones (i.e. those that have nothing to do with *total* and with the blocks where *total* is used for synchronization, but were cached and have an outdated value in main memory). In other words, you didn't mean ALL cached variables of the entire process? (I know it might be a stupid question, but just to make sure...). – Thomas Calc Jun 30 '12 at 23:30
  • 1
    The synchronized uses a memory barrier which ensures ALL memory is in a consistent state for that thread, whether its referenced inside the block or not. – Peter Lawrey Jul 01 '12 at 06:58
0

If my understanding is correct synchronized(total) would synchronize any access to total and thus should synchronize access (read and write) to the values in an array, too.

Since a double array directly contains the values instead of references, those should not be accessible by other threads during execution of the synchronized block. If you had an array of objects you would not be able to change the references in the array but you could still access the objects themselves.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • The problem is that I need both mutual exclusion and up to date values (and references). In your answer you seem to take into account only the first matter. – Lorenzo Pistone Nov 30 '11 at 10:45