挥发性变量和订购前发生的事情

dev*_*ull 12 java volatile

我有两个主题:

主题:1

a = 1;
x = b;
Run Code Online (Sandbox Code Playgroud)

主题:2

b = 1
y = a
Run Code Online (Sandbox Code Playgroud)

这里a和b被声明为volatile.我不明白在a = 1之间如何创建"before-before"边缘; 和y = a; 在x = b之间; 和b = 1;

我知道通过使用volatile变量可以防止从线程缓存中读取过时值.但是,在订购之前,如何确保变量发生变化.

具体来说,我不明白这一点:

对每个后续读取相同字段之前发生对易失性字段的写入.

锄头有用吗?

Jon*_*eet 16

对每个后续读取相同字段之前发生对易失性字段的写入.

这里的重要词是"后续".

以下是Java语言规范17.4.4同步顺序的相关部分:

每次执行都有一个同步顺序.同步顺序是执行的所有同步动作的总顺序.对于每个线程t,t中同步动作(第17.4.2节)的同步顺序与t的程序顺序(第17.4.3节)一致.同步动作引发与动作的同步关系,定义如下:

  • [...]
  • 对volatile变量(第8.3.1.4节)的写入v与任何线程的v的所有后续读取同步(其中后续根据同步顺序定义).

请注意最后一部分.所以它说如果你考虑程序动作的任何总排序,那么后来在总排序中而不是写入的易失性变量的任何读取都不能"错过"写入.


irr*_*ble 5

要进行分析,首先要列出所有可能的同步顺序。它们必须与编程顺序一致。在您的示例中,有 6 个可能的订单。

 1       2       3       4       5       6
w(a)    w(a)    w(b)    w(a)    w(b)    w(b) 
r(b)    w(b)    w(a)    w(b)    w(a)    r(a)
w(b)    r(b)    r(b)    r(a)    r(a)    w(a)
r(a)    r(a)    r(a)    r(b)    r(b)    r(b)
Run Code Online (Sandbox Code Playgroud)

每个订单都建立了一些发生在之前的关系。在(1)中,我们有 w(a) 发生在 r(a) 之前。在(6)中,我们有 w(b) 发生在 r(b) 之前。在(2)-(5)中,我们两者都有。

对于每个可能的 order,给定它建立的happens-before 关系,您需要分析执行以确保它执行您想要的操作。

如果这听起来太难了,那就是。在现实生活中,我们通常会用更简单的情况来限制自己,即只有一个对象被锁定/释放,或者只有一个 volatile 变量被读写。然后它不是太复杂。