日期:2014-05-20  浏览次数:20624 次

并发编程中的安全发布问题
//不安全发布
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的条件那里,我死都没懂。因为两个都是n,同样的n,不管是否一个一个线程执行holder一个没有赋值,都应该相等啊!

可能我比较笨,希望层主包含!可能我的问题也没有表述清楚。我现在很大的一个感受就是,很多时候,一个问题并不是我不知道如何解决,很多时候是我没法把一个问题表述清楚。就像这个问题一样。


注意这句“原因就是构造函数不是原子的,指令可能重排序。”
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.")

要是还不明白我就无能为力了