Search code examples
javaconcurrencyatomicvolatilejava.util.concurrent

Happens before between threads and atomic variable Part 2


Since answer to Happens before between threads and atomic variable was that the asserts don't hold, I need an alternate implementation. Thread1 and Thread2 each update Integers t1 and t2 respectively. Once they are updated no other updates occur to t1 or t2. The values assigned to t1 and t2 come from a common counter which gets incremented after each assignment. I need to ensure the following asserts are true;

int cnt=0;
ReentrantLock lock = new ReentrantLock();
volatile Integer t1=null;
volatile Integer t2=null;

//Thread1
lock.lock();
try{t1=cnt++;}finally{lock.unlock();}
if(t2 == null){
  assert t2==null || t2>t1;
}

//Thread2
lock.lock();
try{t2=cnt++;}finally{lock.unlock();}
if(t1==null){
  assert t1==null || t1>t2;
}

The question is do the asserts hold? Is volatile required on t1 and t2 as shown? Is there a better/correct way to accomplish this?


Solution

    1. Yes, asserts will pass. There is HB between every read and write and there is guarantee that if the first thread get lock, the second one can neither nor increment the counter, nor initialize it's t variable. Therefore if a thread is inside if(t1==null){} t2 will be null or greater then t1. The same is true for another thread.
    2. You can not remove volatile from that code because t1 and t2 are shared between different threads and you need to ensure there is HB between reads and writes of that fields in different threads.
    3. If better solution exists, I am afraid that I am not able to find it so fast. I think any correct solution where it is possible to go inside if(t1==null){...} must meet the requirement: t1=cnt++ must be being performed by only one thread simultaneously.