易失性读取是否发生在易失性写入之前?

我试着理解为什么这个例子是一个正确同步的程序:

a - volatile Thread1: x=a Thread2: a=5 

因为存在冲突的访问(存在对a的写入和读取)所以在每个顺序一致性执行中必须发生 – 在该访问之间的关系之前。 假设一个顺序执行:

 1. x=a 2. a=5 

1发生在2之前,为什么?

不,在易失性写入之前,(同步顺序)之前的易失性读取不一定发生相同变量的易失性写入。

这意味着它们可以处于“数据竞争”中,因为它们是“冲突的访问,而不是由先发生过的关系命令”。 如果这是真的,几乎所有程序都包含数据竞争:)但它可能是一个规范错误。 永远不应将易失性读写视为数据竞争。 如果程序中的所有变量都是易失性的,则所有执行都是顺序一致的。 见http://cs.oswego.edu/pipermail/concurrency-interest/2012-January/008927.html

如果你有一个volatile变量a ,一个线程正在读取它而另一个正在写入它,那么这些访问的顺序可以是任意顺序。 这是一种竞争条件 。 这取决于首先启动的操作。

写入可能刚刚发生,读取看到更新的值。 或者写入可能在读取之后发生。 所以x可以是5或a的前一个值。

每个顺序一致性执行必须在该访问之间的关系之前发生

你在这里误导了。 与volatile发生“在关系之前发生”意味着在保证读取或写入volatile变量之前的所有先前的存储器更新都已完成。 因此,两个线程都具有“之前发生”保证,但这绝不能解释两个volatile访问如何相互作用。 这取决于竞争条件。 读者可以保证看到写入, 前提是写入发生在读取之前。

易失性和发生之前仅在读取字段驱动某些条件时才有用。 例如:

 volatile int a; int b =0; Thread-1: b = 5; a = 10; Thread-2 c = b + a; 

在这种情况下,没有发生 – 之前,a可以是10或0,b可以是5或0,因此结果c可以是0,5,10或15.如果读取a意味着其他一些条件然后发生before-before例如:

 int b = 0; volatile int a = 0; Thread-1: b = 5 a = 10; Thread 2: if(a == 10){ c = b + a; } 

在这种情况下,您将确保c = 15,因为读取a==10意味着在写入b = 5之前发生了b = 5的写入

编辑:更新添加顺序,如灰色所示的不一致

抱歉,您无法正确说出JVM如何根据JVM的“内存模型”优化代码。 您必须使用Java的高级工具来定义您想要的内容。

所以volatile只意味着没有用于变量的“线程间缓存”。

如果您想要更严格的订单,则必须使用同步块。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html