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

时间:2010-10-19 17:39:51

标签: java volatile

我有两个主题:

主题:1

a = 1;
x = b;

主题:2

b = 1
y = a

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

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

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

  

发生对易失性字段的写入   在每次后续阅读之前   相同的领域。

锄头有用吗?

3 个答案:

答案 0 :(得分:16)

  

对易失性字段的写入发生在每次后续读取同一字段之前。

这里的重要词是“后续”。

以下是Java语言规范17.4.4 Synchronization Order的相关部分:

  

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

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

请注意最后一部分。所以它说如果你考虑程序动作的任何总排序,那么读取总顺序后面的一个易失性变量而不是写入就不能“错过”写入。

答案 1 :(得分:4)

要分析,首先列出所有可能的同步订单。它们必须与编程顺序一致。在您的示例中,有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)

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

对于每个可能的订单,给定由它建立的先发生关系,您需要分析执行以确保它能够满足您的需求。

如果这听起来太难了,那就是。在现实生活中,我们通常局限于简单的情况,其中只有一个对象被锁定/释放,或者只有一个易失性变量被读写。然后它不是太复杂。

答案 2 :(得分:3)

  

写入易失性字段发生在每次后续读取同一字段之前。

这篇文章令人困惑。它将发生之前的关系限制为在读取之前发生的写入!它只说在之后发生的读取,实际上发生在。

之后

换句话说,它试图说的是在写入过程中没有发生读取,并且如果还有其他发生在之前的关系导致读取发生在之后写,读取将具有该写入的值。

请参阅JLS部分17.4.4 Synchronization Order,该部分在此上下文中定义了“后续”一词。