Java volatile读刷新写,volatile写更新读吗

Java volatile读刷新写,volatile写更新读吗,java,multithreading,Java,Multithreading,我理解读获取(不在其后使用后续读/写操作重新排序)和写释放(不在之前使用读/写操作重新排序)。 我的问题是:- 在读获取的情况下,它前面的写操作是否被刷新 在写释放的情况下,以前的读取是否得到更新 另外,在Java中,读获取和volatile读相同,写释放和volatile写相同吗 这之所以重要,是因为,让我们以写释放为例 y = x; // a read.. let's say x is 1 at this point System.out.println(y);// 1 printed //

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

  • 在读获取的情况下,它前面的写操作是否被刷新
  • 在写释放的情况下,以前的读取是否得到更新
  • 另外,在Java中,读获取和volatile读相同,写释放和volatile写相同吗

    这之所以重要,是因为,让我们以写释放为例

    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?
    
    此时,是x2还是1? 在这里,考虑一下波动性。 我知道在volatile之前的所有商店都将首先可见。。然后,只有挥发物才可见。谢谢


    参考:-

    对于您的第一个问题,答案是FIFO顺序


    关于第二个问题:请检查

    否:并非所有写入都已刷新,也不是所有读取都已更新

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

    在基本上通过与中定义的关系进行同步来建立边之前发生。有几种不同的方法可以做到这一点,但对于volatile,它基本上相当于在读取同一volatile之前发生对volatile的写入:

    • 对易失性变量v的写入(§8.3.1.4)与任何线程对v的所有后续读取同步(其中“后续”是根据同步顺序定义的)
    鉴于此,如果线程写入
    ready=true
    ,那么单独写入并不意味着在它之前发生任何事情(就写入而言)。事实恰恰相反;如果它们读取
    ready
    ,则写入
    ready
    的操作会在其他线程上的操作之前发生

    因此,如果另一个线程(设置
    x=2
    )在设置
    x=2
    后已写入ready,而这个线程(您在上面发布的)则读取
    ready
    ,那么它将看到
    x=2
    。这是因为写入发生在读取之前,因此读取线程可以看到写入线程所做的一切(包括写入)。否则,你就有了一场数据竞赛,基本上所有的赌注都输掉了

    还有几点需要注意:

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

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

    否,写入易失性变量不会清除缓存中以前读取的值。它只保证刷新以前的写入


    在您的示例中,很明显,
    y
    在最后一行仍然是1。根据前面的输出,只有一个赋值给了
    y
    ,即1。也许这是一个输入错误,您打算编写
    println(x)
    ,但即使这样,2的值也不能保证是可见的。

    Java内存模型没有用“读取获取”和“写入释放”来指定。这些术语/概念来自其他上下文,正如您所引用的文章非常清楚地表明的,它们通常(由不同的专家)用于表示不同的事物

    如果您想了解volatiles在Java中是如何工作的,您需要了解Java内存模型和Java术语。。。这(幸运的)是有充分的根据和精确的说明1。尝试将Java内存模型映射到“读取-获取”和“写入-释放”语义是一个坏主意,因为:

    • “读取-获取”和“写入-发布”的术语和语义没有得到很好的规定,并且

    • 假设的JMM->“读-获取”/“写-发布”语义映射只是JMM的一种可能实现。其他映射可能具有不同的、同样有效的语义


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