并发编程中的安全发布问题
//不安全发布
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
//Holder的代码
public class Holder {
private int n;
public Holder() {this.n = n;}
public void assertSanity() {
if(n != n)
throw new AssertionError("This statement is false.");
}
}
当在多线程环境下执行不安全代码发布的方式,这样会抛出AssertionError么?
里面的n!=n分别是什么含义?
跪求帮助。
------解决方案--------------------
注意这句“原因就是构造函数不是原子的,指令可能重排序。”
n != n也不是原子的!
其编译后的java指令为
aload
getfield //第一次读变量n
aload
getfield //第二次读变量n
if_icmpeq
如果不同步的话,
两次读变量n之间是可能会切换到其它线程执行的。
继续使用我给出的“不安全发布”的例子来说
第一个线程用来new实例,当第二个线程中 sh.holder!=null 时(也就是构造函数已经发布了),
但因为重排序,n有可能尚未赋值,也就是int变量的默认值0。此时第一次读变量n记为n',实际值为0;此时再次切换到线程1完成了n赋值为42,此时第二次读变量n记为n'',实际值为42。
你所看到的n!=n实际是n'!=n'',最后是0!=42,结果为真
执行throw new AssertionError("This statement is false.")
要是还不明白我就无能为力了