“代码一定会跳出 while 循环吗?”
不是的。Java 内存模型是基于“
happens before”关系定义的:
“两个动作可以通过 happens-before 关系进行排序。如果一个动作在另一个动作之前发生,那么第一个动作对第二个动作是可见的并且被排序在其前面。” 规范还指出:
“如果操作 x 与后续操作 y 同步,则我们也有 hb(x,y)。” 其中 hb 表示 happens-before,并且
“监视器 m 上的解锁操作与 m 上所有后续锁定操作同步(其中“后续”根据同步顺序定义)。”
另请注意:
“如果 hb(x, y) 和 hb(y, z),那么 hb(x, z)。”
所以在你的例子中,
synchronized(lock)
包围
b
的操作将会为接下来的读取建立 happens-before 关系,因此
b
的值保证在其他同样使用
synchronized(lock)
的线程中可见。明确地说,
hb(write to b in threadOne, unlock in threadOne) AND
hb(unlock in threadOne, lock in threadTwo) AND
hb(lock in threadTwo, read from a in threadTwo) IMPLIES
hb(write to b in threadOne, read from b in threadTwo)
同样地,
a
将保证对于其他线程是可见的。明确地说,
hb(write to a in threadOne, lock in threadOne) AND
hb(lock in threadOne, unlock in threadOne) AND
hb(unlock in threadOne, lock in threadTwo) AND
hb(lock in threadTwo, read a in threadTwo) IMPLIES
hb(write to a in threadOne, read a in threadTwo).
写入和随后读取 c 没有先于关系,因此根据规范,对 c 的写入不一定对 threadTwo 可见。
如果我们将变量c从方程中移除怎么办? 我想知道是否仅保证在同步块中的 b 可以在threadTwo中可见。
是的,请参见上文。