Java volatile是否读取刷新写入,并执行易失性写入更新读取 [英] Does Java volatile read flush writes, and does volatile write update reads

查看:133
本文介绍了Java volatile是否读取刷新写入,并执行易失性写入更新读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我理解read-acquire(不会重新排序后续的读/写操作)和write-release(不重新排序前面的读/写操作)。
我的q是: -

I understand read-acquire(does not reorder with subsequent read/write operations after it), and write-release(does not reorder with read/write operations preceding it). My q is:-


  1. 如果是read-acquire,它之前的写操作是否会被刷新?

  2. 如果是写入释放,先前的读取是否会更新?

此外,是读取 - 获取与volatile中的volatile读取和写入释放相同吗?

Also, is read-acquire same as volatile read, and write release same as volatile write in Java?

为什么这很重要,让我们来看看写入释放的情况..

Why this is important is that, let's take case of write-release..

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会被看到。谢谢。

At this point, is x 2 or 1? Here, consider ready to be volatile. I understand that all stores before volatile will first be made visible.. and then only the volatile will be made visible. Thanks.

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

推荐答案

否:不所有写入都被刷新,所有读取都没有更新。

No: not all writes are flushed, nor are all reads updated.

Java工作在多线程的先发生基础上。基本上,如果A发生在B之前,B发生在C之前,那么A发生在C之前。所以你的问题等于 x = 2 正式发生 - 在某些情况发生之前读取x的动作。

Java works on a "happens-before" basis for multithreading. Basically, if A happens-before B, and B happens-before C, then A happens-before C. So your question amounts to whether x=2 formally happens-before some action that reads x.

发生前 - 边缘基本上是通过同步关系建立的,这些关系在 JLS 17.4.4 。有几种不同的方法可以做到这一点,但对于挥发性物质来说,它基本上等于对易失性事件的写入 - 在读取相同的易失性之前:

Happens-before edges are basically established by synchronizes-with relationships, which are defined in JLS 17.4.4. There are a few different ways to do this, but for volatiles, it's basically amounts to a write to volatile happening-before a read to that same volatile:



  • 写入易失性变量v(§8.3.1.4)与任何线程的所有后续v读取同步 - 其中后续定义为到同步顺序)。

  • 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 发生在其他线程上的事情之前,如果他们读取 ready

Given that, if your thread writes ready = true, then that write alone doesn't mean anything happens-before it (as far as that write is concerned). It's actually the opposite; that write to ready happens-before things on other threads, iff they read ready.

因此,如果另一个线程(设置 x = 2 )在之后写入,则设置 x = 2 ,这个帖子(你上面发布的)然后准备,然后呢会看到 x = 2 。这是因为写入发生在读取之前,因此读取线程会看到写入线程已完成的所有操作(直到并包括写入)。否则,你有数据竞争,基本上所有的赌注都已关闭。

So, if the other thread (that sets x = 2) had written to ready after it set x = 2, and this thread (that you posted above) then read ready, then it would see x = 2. That is because the write happens-before the read, and the reading thread therefore sees everything that the writing thread had done (up to and including the write). Otherwise, you have a data race, and basically all bets are off.

另外几个注释:


  • 如果您没有事先发生的优势,可能仍会看到更新;只是你不能保证。所以,不要假设如果你没有读到 ready 的写入,那么你仍然会看到x = 1。您可能会看到x = 1或x = 2,或者可能是其他一些写入(最多并包括默认值x = 0)

  • 在您的示例中, y 总是为1,因为在somewhere here注释后你没有重新读取 x 。出于这个答案的目的,我假设在 ready = true y = x 行>。如果没有,则y的值将与第一个 println 中的值保持不变(假设没有其他线程直接更改它 - 如果它是局部变量,则保证),因为线程中的操作总是显得好像没有重新排序。

  • If you don't have a happens-before edge, you may still see the update; it's just that you're not guaranteed to. So, don't assume that if you don't read a write to ready, then you'll still see x=1. You might see x=1, or x=2, or possibly some other write (up to and including the default value of x=0)
  • In your example, y is always going to be 1, because you don't re-read x after the "somewhere here" comment. For purposes of this answer, I've assumed that there's a second y=x line immediately before or after ready = true. If there's not, then y's value will be unchanged from what it was in the first println, (assuming no other thread directly changes it -- which is guaranteed if it's a local variable), because actions within a thread always appear as if they are not reordered.

这篇关于Java volatile是否读取刷新写入,并执行易失性写入更新读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆