问题
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?
回答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 insideif(t1==null){}
t2
will benull
or greater then t1. The same is true for another thread. - You can not remove
volatile
from that code becauset1
andt2
are shared between different threads and you need to ensure there is HB between reads and writes of that fields in different threads. - 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.
回答2:
There is a possibility of thread1 writing to t1 after thread2 has executed if (t1 == null ) before reaching corresponding assert statement or vice versa.
If statement and assert following it should be executed within a synchronized context.
来源:https://stackoverflow.com/questions/53365250/happens-before-between-threads-and-atomic-variable-part-2