java - Java volatile read flush writes,和volatile write update reads

标签 java multithreading

我理解读取-获取(不对其后的后续读/写操作重新排序)和写-释放(不对其之前的读/写操作重新排序)。 我的问题是:-

  1. 在读取-获取的情况下,它之前的写入是否被刷新?
  2. 在写入释放的情况下,之前的读取是否得到更新?

另外,java中read-acquire和volatile read一样,write release和volatile write一样吗?

为什么这很重要,让我们以写释放为例..

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? 在这里,考虑准备好波动。 我知道 volatile 之前的所有商店都将首先可见..然后只有 volatile 才会可见。谢谢。

引用:- http://preshing.com/20120913/acquire-and-release-semantics/

最佳答案

不:不是所有的写入都被刷新,也不是所有的读取都被更新。

Java 在多线程处理的“先发生”基础上工作。基本上,如果 A happens-before B,B happens-before C,那么 A happens-before C。所以你的问题是 x=2 是否正式 happens-before 一些读取 x 的 Action 。

Happens-before 边基本上是由同步关系建立的,定义在 JLS 17.4.4 中。 .有几种不同的方法可以做到这一点,但对于 volatiles,它基本上相当于写入 volatile happening-before a read to the same volatile:

  • A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

鉴于此,如果您的线程写入 ready = true,那么单独写入并不意味着在它之前发生任何(就写入而言) .实际上恰恰相反;写入 ready happens-before things on other threads, iff they read ready.

因此,如果另一个线程(设置 x = 2)在设置 x = 2 之后写入就绪 ,这线程(您在上面发布的)然后读取就绪,然后它会看到x = 2。那是因为写入发生在读取之前,因此读取线程可以看到写入线程所做的一切(直到并包括写入)。否则,您将面临数据竞争,基本上所有赌注都会落空。

一些补充说明:

  • 如果您没有先行发生边缘,您可能仍会看到更新;只是你不能保证。所以,不要假设如果您不读取写入 ready,那么您仍然会看到 x=1。您可能会看到 x=1 或 x=2,或者可能会看到一些其他写入(直到并包括默认值 x=0)
  • 在您的示例中,y 始终为 1,因为您不会在“此处某处”注释后重新阅读 x。出于此答案的目的,我假设在 ready = true 之前或之后有第二个 y=x 行。如果没有,则 y 的值将与第一个 println 中的值保持不变(假设没有其他线程直接更改它——如果它是局部变量,则可以保证),因为线程总是看起来好像没有重新排序。

关于java - Java volatile read flush writes,和volatile write update reads,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35808193/

相关文章:

java - 动画控制Jmonkey

java - 使用 Firebase Messaging 实现通知时出现空指针异常

c++ - 线程安全队列C++

java - 使用ArrayBlockingQueue和mutex的多线程代码中的疑问

java - 在 Assert.fail() 中添加消息

java - 我正在尝试将文件路径(4 个文件)和文件元数据存储到 hashmap。如何做到这一点?我正在使用蒂卡API

java - 如何在 Java 中将未检查的异常转换/包装为已检查的异常?

java的synchronized关键字的C#版本?

Swift OSX - 从另一个类或者线程更新 NSTextView

java - Objective-C 中是否允许嵌套同步块(synchronized block)?