2016-03-04 129 views
16

我明白读取获取(不会对其后的读取/写入操作进行重新排序)和写入释放(不会对其前面的读取/写入操作进行重新排序)。 我的问题是: -Java易失性读取刷新写入和易失性写入更新读取

  1. 在读取获取的情况下,执行它之前的写入刷新?
  2. 在写入释放的情况下,先前的读取是否更新?

此外,是读取获取相同的易失性读取,并释放相同的易失性写在Java中?

为什么这是重要的是,让我们写释放的情况下..

y = x; // a read.. let's say x is 1 at this point 
System.out.println(y);// 1 printed 
//or you can also consider System.out.println(x); 
write_release_barrier(); 
//somewhere here, some thread sets x = 2 
ready = true;// this is volatile 
System.out.println(y);// or maybe, println(x).. what will be printed? 

在这一点上,为x 2或1? 在这里,考虑准备好变化。 据我所知,在易失性之前的所有商店将首先变得可见..然后只有易失性将变得可见。谢谢。

参考: - http://preshing.com/20120913/acquire-and-release-semantics/

回答

10

号:不是所有的写操作都脸红了,也不是所有的读更新。

Java在多线程的“发生之前”基础上工作。基本上,如果A发生在B之前,B发生在C之前,那么A发生在C之前。因此,你的问题等于x=2正式发生 - 在某个读取x的动作之前。

发生前边缘基本上是通过与JLS 17.4.4中定义的关系同步建立的。有几种不同的方式来做到这一点,但对于挥发物,它基本上相当于一个写挥发发生,之前的读取到同一挥发性:

  • 写一个volatile变量v(§8.3 .1.4)同步 - 任何线程(其中“后续”根据同步顺序定义)对v的所有后续读取。

鉴于此,如果您的线程写入ready = true,然后单独写并不意味着什么之前发生它(只要是写而言)。实际上恰恰相反;写到ready发生在其他线程的事情之前,如果他们读取ready

因此,如果其他线程(即设置x = 2)曾之后写入准备它设置x = 2,并且此线程(你上面贴)然后ready,那就看x = 2。这是因为在读取之前写入发生,并且读取线程因此看到写入线程已完成的所有内容(直到并包括写入)。否则,你有一场数据竞赛,基本上所有的赌注都没有了。

一对夫妇的其他注意事项:

  • 如果没有之前发生边缘,你可以仍然看到更新;这只是你不能保证。所以,不要假设,如果你没有读ready,那么你仍然会看到x = 1。您可能会看到x = 1或x = 2,或者可能还有其他一些写入(直到并包括x = 0的默认值)
  • 在您的示例中,y始终为1,因为您不重新阅读x之后的“某处here”评论。为了达到这个答案,我假设在ready = true之前或之后有第二行y=x。如果不存在,那么y的值将与第一个println中的值相同(假设没有其他线程直接更改它 - 如果它是局部变量,则保证这一点),因为线程内的动作总是显示为好像它们是不重新排序。
5

不,读取volatile变量不会刷新前面的写入。可见操作将确保前面的操作是可见的,但读取volatile变量对其他线程不可见。

不,写入volatile变量不会清除之前读取的值的缓存。只保证刷新先前的写入。

在你的例子中,在最后一行显然y仍然是1。根据前面的输出,对y只做了一项分配,这是1。也许这是一个错字,你的意思是写println(x),但即使如此,2的值也不能保证可见。

7

Java内存模型没有用“read-acquire”和“write-release”来指定。这些术语/概念来自其他背景,并且由于您引用的文章非常清晰,它们经常被不同专家用来表示不同的东西。

如果您想了解Java中的挥发性物质是如何工作的,您需要了解Java存储器模型和Java术语......这是(幸运的是)有根据且精确地指定了。试图将Java的内存模型映射到“读 - 获取”和“写释放”语义是一个糟糕的主意,因为:

  • “读 - 获取”和“写释放”术语和语义并不好指定,并且

  • 一个假设的JMM->“read-acquire”/“write-release”语义映射只是JMM的一种可能的实现。其他映射可能存在,具有不同且同样有效的语义


1 - ...那个专家已经注意到在JMM的某些版本中的缺陷模。但重要的是,已经做出了认真的尝试来提供理论上合理的规范......作为Java语言规范的一部分。