Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 围绕易失性字段对正常字段重新排序_Java_Multithreading - Fatal编程技术网

Java 围绕易失性字段对正常字段重新排序

Java 围绕易失性字段对正常字段重新排序,java,multithreading,Java,Multithreading,基于 volatile做什么 及 对易失性的新保证 看来 1a) write to non-volatile variable x 1b) write to volatile variable v 1a永远不能通过1b移动 我想知道,我是否将源代码修改为 class VolatileExample { int x = 42; volatile boolean v = true; public void writer() { v = false; x = 0;

基于

volatile做什么

对易失性的新保证

看来

1a) write to non-volatile variable x 
1b) write to volatile variable v
1a永远不能通过1b移动

我想知道,我是否将源代码修改为

class VolatileExample {
  int x = 42;
  volatile boolean v = true;
  public void writer() {
    v = false;
    x = 0;
  }

  public void reader() {
    if (v == true) {
      //uses x - guaranteed to see 42?????
    }
  }
}
下面的顺序可以排列吗

2a) write to volatile variable v
2b) write to non-volatile variable x
我想知道,2b能在2a之前移动吗?这是因为如果2b能在2a之前移动,读者就不能再保证在if块中看到42

根据以下信息,我觉得2b可以在2a之前移动。


写入易失性字段具有 与显示器具有相同的记忆效果 释放,并从一个易失性 字段与字段具有相同的记忆效果 监视获取


这意味着任何内存操作 之前的线程都可以看到 退出同步的块是 任何线程进入后都可见 受保护的同步块 相同的监视器,因为所有的内存 操作发生在发布之前, 释放发生在 获得



volatile_v=true volatile有两个部分,指令顺序和写入的“刷新”

指令的顺序不会改变,但两段代码之间可能存在任何延迟,因此在第二种情况下,x可能是42,但可能是0。我猜你会更经常地看到0


根据您的体系结构,这可能比在其他系统上更可能发生,因此在一台机器上测试发现它是42,并不意味着它将始终在另一台机器上。

据我了解,新的内存模型,一旦易失性值刷新到主内存,冲洗线程可以看到的所有其他变量也必须冲洗。但这样做的结果是,虚拟机无法将2b重新排序到2a之前,因为这将违反代码中隐含的“在之前发生”排序。

我认为您不能保证这一点,因为类实例字段x没有封装,包可见可以由另一个线程更改。将x变量设置为volatile将解决这个问题,并保证所有线程的可见性。

我们知道,对volatile变量的写入不能根据之前的任何读取或写入(从Java5开始)重新排序,但反过来就不是这样了。因此,将程序重新排序为x=0;v=假;据我所知是正确的

在我们写入v之后,我们可以保证在读取v时,在写入v之前发生的每一个动作都是可见的,但它并没有说明写入v之后的任何动作——这些动作可能已经发生,也可能没有发生,甚至可以重新排序以在写入v之前发生。

语句2b(写入非易失性变量x)可以移动到语句2a之前(写入易失性变量v),即,另一个线程可能看到
v==true
x==0

请注意,即使不重新排序另一个线程,也可能会看到这些值


假设已创建并初始化了
VolatileExample
的实例。线程T1在该实例上执行方法
reader
。它看到
v==true
,并被调度程序中断。调用方法
writer
的第二个线程现在可以执行赋值
v=false
x=0
。当T1恢复并读取
x
时,它可能读取值0(但不能保证看到0)。如果它看到值0,那么我们就有了这样的情况,T1看到
v==true
x==0
。对于T1来说,这两条语句似乎已被重新排序。由于这种状态可以在不重新排序的情况下观察到,因此实际上允许重新排序是有道理的。

为什么说指令顺序不会改变?你有什么具体的参考资料吗?好吧,同样的参考资料基本上说明volatile上的指令不会向前或向后移动。操作顺序并不重要。这是一个单独的操作问题。正如@Peter指出的,调用
reader()
的线程可能会进入if块,然后无限期地延迟。当它最终被重新安排执行时,x现在可能是0。你能得到任何具体的例子吗,重新排序可能会发生?这种行为的例子可能非常难以获得(这是问题的本质),但对于第一个声明,我可以引用:-正在使用Volatile修复双重检查锁定的部分。这篇文章的其余部分是基于。未指定在写入易失性变量之前不能对写入进行重新排序,即它应该是有效的。在2a之前移动2b不得违反“发生在”关系<代码>如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序。
在第二个动作之前不会发生任何动作。因此,将2b移到2a以上应该是好的。
2a) write to volatile variable v
2b) write to non-volatile variable x
volatile_v = true;      <-- monitor release
non_volatile_x = 42;
(volatile_v will act as a roach motels, and it is fine for non_volatile_x to move into roach motels)


non_volatile_x = 42;
volatile_v = true;      <-- monitor release
(volatile_v will act as a roach motels, and it is not OK for non_volatile_x to move out from roach motels)