在线程和原子变量之间发生之前第 2 部分
Happens before between threads and atomic variable Part 2
由于对 的回答是断言不成立,我需要一个替代实现。 Thread1 和 Thread2 分别更新整数 t1 和 t2。一旦它们被更新,t1 或 t2 就不会再发生其他更新。分配给 t1 和 t2 的值来自一个公共计数器,该计数器在每次分配后递增。我需要确保以下断言为真;
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;
}
问题是断言是否成立?如图所示,t1 和 t2 是否需要 volatile?有没有 better/correct 方法来完成这个?
线程 1 有可能在线程 2 执行 if (t1 == null ) 之后到达相应的断言语句之前写入 t1,反之亦然。
If 语句及其后的断言应在同步上下文中执行。
- 是的,断言会通过。每次读取和写入之间都有 HB,并且可以保证如果第一个线程获得锁定,第二个线程既不能增加计数器,也不能初始化它的
t
变量。因此,如果线程在 if(t1==null){}
内,t2
将是 null
或更大,然后 t1。另一个线程也是如此。
- 您不能从该代码中删除
volatile
,因为 t1
和 t2
在不同线程之间共享,您需要确保在该字段的读写之间存在 HB不同的线程。
- 如果有更好的解决办法,恐怕我没办法这么快找到。我认为任何可以进入
if(t1==null){...}
的正确解决方案都必须满足要求:t1=cnt++
必须同时由一个线程执行。
由于对
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;
}
问题是断言是否成立?如图所示,t1 和 t2 是否需要 volatile?有没有 better/correct 方法来完成这个?
线程 1 有可能在线程 2 执行 if (t1 == null ) 之后到达相应的断言语句之前写入 t1,反之亦然。
If 语句及其后的断言应在同步上下文中执行。
- 是的,断言会通过。每次读取和写入之间都有 HB,并且可以保证如果第一个线程获得锁定,第二个线程既不能增加计数器,也不能初始化它的
t
变量。因此,如果线程在if(t1==null){}
内,t2
将是null
或更大,然后 t1。另一个线程也是如此。 - 您不能从该代码中删除
volatile
,因为t1
和t2
在不同线程之间共享,您需要确保在该字段的读写之间存在 HB不同的线程。 - 如果有更好的解决办法,恐怕我没办法这么快找到。我认为任何可以进入
if(t1==null){...}
的正确解决方案都必须满足要求:t1=cnt++
必须同时由一个线程执行。