发生在线程和原子变量之间 [英] Happens before between threads and atomic variable
问题描述
假设一个AtomicInteger c
在两个线程(线程1和线程2)之间共享. Thread1使用c.incrementAndGet()
设置(仅一次)易失性变量t1
. Thread2使用c.incrementAndGet()
设置(仅一次)易失变量t2
.一旦设置了t1和t2,就不会再由其他任何线程对其进行设置.假设线程1设置t1
之后,它检查t2
的值并获取null
.是否保证随后将t2
设置为比t1
更高的值? (反之亦然).换句话说,下面的断言是否总是正确的?那是为什么呢?
Suppose an AtomicInteger,c
, is shared between two threads, thread1 and thread2. Thread1 sets (one time only) a volatile variable t1
using c.incrementAndGet()
. Thread2 sets (one time only) a volatile variable t2
using c.incrementAndGet()
. Once t1 and t2 are set they are not set again by any other thread. Suppose that after thread1 sets t1
, it checks the value of t2
and gets null
. Is it guaranteed that t2
is subsequently set to a higher value then t1
? (and visa versa). In other words are the assert below always true? Is so why?
AtomicInteger c = new AtomicInteger();
volatile Integer t1=null;
volatile Integer t2=null;
//Thread1
t1=c.incrementAndGet();
if(t2 == null){
assert t2==null || t2>t1;
}
//Thread2
t2=c.incrementAndGet();
if(t1==null){
assert t1==null || t1>t2;
}
我认为这些断言是正确的,原因如下:如果为t1分配了c的增量值,并且尚未为t2分配c的增量值,那么当随后为t2分配c的值时,t2必须为大于t1的值.
I believe the asserts are true for the following reason: If t1 is assigned a value from incrementing c and t2 has not yet been assigned a value by incrementing c then when t2 is subsequently assigned a value by incrementing c, it must be greater then the value of t1.
更新:由于根据断言下面的正确答案可能并不总是成立,因此我添加了第2部分的问题:请查看发生在线程和原子变量第2部分之间.
Update: Since as per the correct answer below the asserts may not always hold, I have added a part 2 question: Check out Happens before between threads and atomic variable Part 2.
推荐答案
不,不能保证.可能会发生以下情况:
No, there's no guarantee. The following could happen:
- thread2:c.incrementAndGet(c为1,t2仍为null,但稍后将用1初始化)
- thread1:c.incrementAndGet(c为2,t1仍为null,但稍后将用2初始化)
- 线程1:t1 = 2
- 线程1:如果(t2 == null):条件为true. if块被评估
- 线程2:t2 = 1
- thread1:t2 == null:条件为false,因此计算
or
的另一个操作数 - 线程1:t2> t1:false,因为t2为1而t1为2
- 线程1:断言:失败
- thread2: c.incrementAndGet (c is 1, and t2 is still null, but will be initialized with 1 later)
- thread1: c.incrementAndGet (c is 2, and t1 is still null, but will be initialized with 2 later)
- thread1: t1 = 2
- thread1: if (t2 == null): the condition is true. The if block is evaluated
- thread2: t2 = 1
- thread1: t2 == null: the condition is false, so the other operand of the
or
is evaluated - thread1: t2 > t1: false since t2 is 1 and t1 is 2
- thread1: assert: fails
这篇关于发生在线程和原子变量之间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!