!不同! 之间的总顺序易失变量?
考虑以下 Java 代码:
volatile boolean v1 = false;
volatile boolean v2 = false;
//Thread A
v1 = true;
if (v2)
System.out.println("v2 was true");
//Thread B
v2 = true;
if (v1)
System.out.println("v1 was true");
如果存在全局可见的易失性访问总顺序,则始终会到达至少一个 println。
Java 标准确实保证了这一点吗?或者像这样的执行是可能的:
A: v1 = true;
B: v2 = true;
A: read v2 = false;
B: read v1 = false;
A: v2 = true becomes visible (after the if)
B: v1 = true becomes visible (after the if)
我只能找到有关访问标准中相同 易失性变量的语句(但我可能会遗漏一些东西)。
“对易失性变量 (§8.3.1.4) v 的写入与任何线程对 v 的所有后续读取进行同步(其中后续是根据同步顺序定义的)。”
http://java.sun.com/ docs/books/jls/third_edition/html/memory.html#17.4.4
谢谢!
Consider the following Java code:
volatile boolean v1 = false;
volatile boolean v2 = false;
//Thread A
v1 = true;
if (v2)
System.out.println("v2 was true");
//Thread B
v2 = true;
if (v1)
System.out.println("v1 was true");
If there was a globally visible total order for volatile accesses then at least one println would always be reached.
Is that actually guaranteed by the Java Standard? Or is an execution like this possible:
A: v1 = true;
B: v2 = true;
A: read v2 = false;
B: read v1 = false;
A: v2 = true becomes visible (after the if)
B: v1 = true becomes visible (after the if)
I could only find statements about accesses to the same volatile variable in the Standard (but I might be missing something).
"A write to a volatile variable (§8.3.1.4) v synchronizes-with all subsequent reads of v by any thread (where subsequent is defined according to the synchronization order)."
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.4
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
v1/v2的易失性读/写这4个动作都是同步动作。执行对它们有一个同步顺序,这是一个全序。顺序必须保持每个线程的程序顺序。
这使得推理变得非常容易。显然,至少对于 2 个变量中的 1 个,按照“同步顺序”,对其进行写入的顺序在读取之前进行。因此,写入与读取“同步”。因此,写入“发生在读取之前”。因此,写入对于读取是可见的。
The 4 actions, volatile read/write of v1/v2, are all synchronization actions. An execution has a synchronization order over them, which is a total order. The order must keep the program order of each thread.
That makes reasoning very easy. Obviously at least for 1 of the 2 variables, the write to it is ordered before the read from it, in the 'synchronization order'. Therefore, the write 'synchronizes-with' the read. Therefore, the write 'happens-before' the read. Therefore, the write is visible to the read.
我认为这句话比你意识到的更能回答你的问题。
当线程
A
尝试读取变量时,第 2 行中线程B
对v2
的写入被线程A
“看到”。我将引用的关键部分加粗:
I think the quote answers your question more than you realize it does.
The write to
v2
by threadB
in line #2 is "seen" by threadA
when it attempts to read the variable.I've bolded the key part of the quote:
由于
v2
是易失性
,因此执行中的第三行是不可能的。如果
v2
不是易失性
,则线程 A 可以看到v2
的本地缓存副本,但该副本仍为false
。然而,由于 v2 是易失性的,因此每次读取都将直接进入主内存,因此将看到最近写入的值。
也就是说,我不认为对不同全局变量的访问之间存在任何特定的顺序保证,但我也不认为这对您的示例有影响。
The third line in your execution is not possible, due to the fact that
v2
isvolatile
.If
v2
were notvolatile
, thread A could see a locally-cached copy ofv2
that was stillfalse
.Since
v2
is volatile, however, every read will go directly to main memory, and will thus see the most recently-written value.That said, I don't believe there are any specific ordering guarantees between accesses to different global variables, but I also don't believe it makes a difference in your example.
Java 中的易失性变量始终是顺序一致的。因此它们的执行与所有易失性加载和存储的顺序执行一致。在此顺序执行中,所有加载和存储都有一个总顺序(因此在不同地址上加载和存储;而不仅仅是在单个地址上)。
所以你的例子中的执行是不允许的。
Volatile variables in Java are always sequential consistent. So their execution is consistent with a sequential execution of all volatile loads and stores. In this sequential execution there is a total order over all loads and stores (so loads and stores over different addresses; not just over a single address).
So the execution in your example is not allowed.
嗯...根据 volatile 的定义,如果 B 将 v2 设置为 true,那么 A 就无法将其读取为 false。
易失性使数据类型和引用在执行单个操作时线程化时按预期工作(因此 ++ 和 -- 不起作用!)
Well...by the definition of volatile if v2 was set to true by B, then A can't read it as false.
volatile makes data types and references work as expected when threading when doing single opeartions (so ++ and -- don't work!)
简而言之:至少会打印一次,因为两个易失性操作不能重新排序。
我不知道规范中在哪里写到,但 Doug Lea 网站上有一个表,哪些操作可以重新排序,哪些操作不能重新排序。 (http://gee.cs.oswego.edu/dl/jmm/cookbook。 html )
这种情况是不可能的,因为读取是在线程启动之前进行初始化
错误!
如果仅在这种情况下,您的情况就有可能,但是< /strong> 这是不可能的,因为 v2 和 v1 是易失性的,写入 v1 必须在读取 v2 之前 并且 写入 v2 必须在读取 v1 之前
错误!
Briefly: At least once will be printed, because the two volatile operations can not be reordered.
I do not know where it is written about in the specification, but on the Doug Lea site have a table which operations can reorder and what does not. ( http://gee.cs.oswego.edu/dl/jmm/cookbook.html )
This situation is not possible, because read is initialization happens before thread start
WRONG!
You situation possible if only in this situation, but it is not possible because v2 and v1 is volatile and write to v1 must be before read v2 AND write to v2 must be before read v1
WRONG!