Java volatile是否读取刷新写入,并执行易失性写入更新读取 [英] Does Java volatile read flush writes, and does volatile write update reads
问题描述
我理解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:-
- 如果是read-acquire,它之前的写操作是否会被刷新?
- 如果是写入释放,先前的读取是否会更新?
此外,是读取 - 获取与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-readx
after the "somewhere here" comment. For purposes of this answer, I've assumed that there's a secondy=x
line immediately before or afterready = true
. If there's not, then y's value will be unchanged from what it was in the firstprintln
, (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屋!