更新时间:2023-11-15 09:06:40
否:不所有写入都被刷新,所有读取都没有更新。
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
中的值保持不变(假设没有其他线程直接更改它 - 如果它是局部变量,则保证),因为线程中的操作总是显得好像没有重新排序。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)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.