[英]Inconsistent State Comparison Java
In Java Concurrency In Practice an example* is given to demonstrate the issue of visibility , where two different threads may not see the up-to-date state of any particular mutable object because of a lack of synchronisation. 在Java Concurrency In Practice中 ,给出了一个示例*来演示可见性问题,其中两个不同的线程由于缺少同步而可能看不到任何特定可变对象的最新状态。
public class Holder {
private int n;
public Holder(int n) { this.n = n; }
public void assertSanity() {
if (n != n){
throw new AssertionError("This statement is false.");
}
}
In this particular example, the book states that should a Thread "A" first initialise and publish it via a Thread unsafe manner, like: 在此特定示例中,该书指出应首先初始化线程“ A”并通过线程不安全的方式发布它,例如:
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
And then a Thread "B" calls holder.assertSanity()
, that it is entirely possible that the AssertionError
will be thrown, due to an inconsistent state. 然后,线程“ B”调用
holder.assertSanity()
,由于状态不一致,很有可能引发AssertionError
。
Now, I understand the basic premise of the argument, where a change made to a mutable variable may never be observed by another thread. 现在,我了解了该参数的基本前提,即对可变变量所做的更改可能永远不会被另一个线程观察到。 But what I am confused here is the fact that it is comparing the same (or so I think) reference
n != n
. 但是我在这里感到困惑的是,它正在比较相同的(或我认为)参考
n != n
。
Doesn't this compare the value of the mutable primitive field private int n
? 这不比较可变基本字段
private int n
吗? Regardless of the fact that n
may now be of value 42 to Thread A, and of value 0 (default) to Thread B, shouldn't a direct call to check it's value in the same thread be consistent ? 不管现在线程A的
n
值可以为42,线程B的n
值可以为0(默认值),无论是否直接调用以检查同一线程中的值是否一致 ? ie Calling assertSanity()
in Thread A would check if 42 != 42
, and in Thread B, 0 != 0
? 即在线程A中调用
assertSanity()
将检查是否42 != 42
,在线程B中是否为0 != 0
?
*Referenced from 3.5 Safe Publication, Listings 3.14 & 3.15 in the book. *参考3.5安全出版物中的清单3.14和3.15。
The problem is that in the expression n != n
the variable n
will be loaded twice (assuming no optimization of the bytecode). 问题在于,在表达式
n != n
,变量n
将被加载两次(假设未对字节码进行优化)。 Between these two loads, another thread could change the value. 在这两个负载之间,另一个线程可以更改该值。
During comparing in thread B n != n
, B retrieve n
two times. 在线程B中比较
n != n
,B检索n
两次。 Meanwhile the constructor runs in thread A would modify the value of n, from default 0, to 42. 同时,在线程A中运行的构造函数会将n的值从默认0修改为42。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.