Question

I want to know if the JMM will permit an implementation to reorder the access to the ai and ada variables to behave differently than the intention shown in the code.

The intention is that the method perform ops is the next:

  1. gets the next index of an array of volatile items
  2. writes a number in the newly obtained index
  3. performs a spinlock waiting to be sure that older indexes of the array got it's value
  4. prints the sum of the array from the first index to the current obtained one.

What happens after the index reached 1000 is non-important to me. I actually want to use the array as a ring, but if this question gets answered I will be able to figure out how to do it.

Basically I want to avoid locks and rely on atomic and lock-free objects. I don't know however if in this specific case I still need implicit synchronization.

AtomicInteger ai = new AtomicInteger(0);
// let's say all values are null by default
AtomicDoubleArray ada = new AtomicDoubleArray(1000); 
int rn = 4; // dice rolled...

void perfomOps(AtomicInteger ai, AtomicDoubleArray ada) {
   int i = ai.getAndIncrement();
   ada.set(i, rn); 
   spinlock(ada, i);
   printSum(ada, i);
}

void spinlock(AtomicDoubleArray ada, int idx) {
// spinlock in case the other threads couln't write to older indexes yet
   if (idx > 0)
      for (int c = 0;c < idx; c++) 
         while (i = ada.get(c) == null);
}

void printSum(AtomicDoubleArray ada, int idx) {
   double sum = 0;
   for (int i = 0;i < idx; i++)
      sum = sum + ada.get(i);
   Sytem.out.println(sum);
}

// thread 1
perfomOps(ai, ada); // lets say we get 4 printed

// thread 2
perfomOps(ai, ada); // lets say we get 8 printed

// thread 3
perfomOps(ai, ada); // lets say we get 12 printed

Other threads will keep doing the same, it can happen that the print order is not as expected, like 8, 12 and then 4. But assuming a next thread comes in, then it will see correct values and correctly print now 16.

All this fancy stuff is to avoid making explicit locks in order to measure which one performs better, the lockfree version or the synchronized one

Was it helpful?

Solution

The most important rule of the Java Memory Model is (§17.4.5):

A program is correctly synchronized if and only if all sequentially consistent executions are free of data races. If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent (§17.4.3).

If all shared variables are volatile or atomic, then there are no data races. That means sequential consistency is guaranteed. And that means, there will be no reorderings visible in the behaviour of the program.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top