在线程和原子变量之间发生之前第 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 语句及其后的断言应在同步上下文中执行。

  1. 是的,断言会通过。每次读取和写入之间都有 HB,并且可以保证如果第一个线程获得锁定,第二个线程既不能增加计数器,也不能初始化它的 t 变量。因此,如果线程在 if(t1==null){} 内,t2 将是 null 或更大,然后 t1。另一个线程也是如此。
  2. 您不能从该代码中删除 volatile,因为 t1t2 在不同线程之间共享,您需要确保在该字段的读写之间存在 HB不同的线程。
  3. 如果有更好的解决办法,恐怕我没办法这么快找到。我认为任何可以进入 if(t1==null){...} 的正确解决方案都必须满足要求:t1=cnt++ 必须同时由一个线程执行。