3 回答

TA贡献1982条经验 获得超2个赞
是的,可以保证线程2将打印“ done”。当然,也就是说,如果b
线程1中的写入实际上发生b
在线程2中的读取之前,而不是同时发生或更早!
推理的核心是事前发生的关系。多线程程序执行被视为由事件组成。事件可以通过事前发生关系来关联,即一个事件先于另一个事件发生。即使两个事件没有直接关联,如果您可以跟踪从一个事件到另一个事件的一系列先发生后关系,那么您可以说一个事件先于另一个事件发生。
就您而言,您有以下事件:
线程1写入
s
线程1写入
b
线程2从读取
b
线程2从读取
s
以下规则起作用:
“如果x和y是同一线程的动作,并且x按程序顺序位于y之前,则hb(x,y)。” (程序顺序规则)
“在每次对该字段进行后续读取之前,都会对易失字段(第8.3.1.4节)进行写操作。” (波动性规则)
因此,存在以下先于关系:
线程1写入
s
发生在线程1写入b
之前(程序顺序规则)线程1写入
b
发生在线程2从b
(易失性规则)读取之前发生线程2读取
b
发生在线程2读取s
之前(程序顺序规则)
如果您遵循该链,则可以看到以下结果:
线程1写入
s
发生在从线程2读取之前s

TA贡献2041条经验 获得超4个赞
是否可以保证打印“完成”?
如Java并发实践中所述:
当线程
A
写入到一个volatile
变量,然后线程B
读取相同的变量,那名至A之前写可见的所有变量的值volatile
读取后变量变得可见到Bvolatile
变量。
所以是的,这保证打印“完成”。
如果不是将b声明为volatile而是将写入和读取放入同步块,会发生什么情况?
这也将保证相同。
不要使用volatile来保护多个共享状态。
为什么?
因为,volatile仅保证可见性。它不能保证原子性。如果我们在一个线程正在访问的方法中有两个易失性写操作,A
而另一个线程B
正在访问这些易失性变量,则在线程A
执行该方法时,线程有可能在操作中间A
被线程抢占B
(例如在第一次volatile写入之后但在第二次volatile写入之前A
)因此,保证操作的原子性synchronization
是最可行的出路。
添加回答
举报