是!=检查线程是否安全?

问题:

我知道诸如i++的复合操作不是线程安全的,因为它们涉及multiple操作。
但是检查引用本身是否有线程安全的操作?

a != a //is this thread-safe

我试图编程这个并使用多个线程,但没有失败。我想我无法模拟我的机器上的比赛。

编辑:

public class TestThreadSafety {
    private Object a = new Object();

    public static void main(String[] args) {

        final TestThreadSafety instance = new TestThreadSafety();

        Thread testingReferenceThread = new Thread(new Runnable() {

            @Override
            public void run() {
                long countOfIterations = 0L;
                while(true){
                    boolean flag = instance.a != instance.a;
                    if(flag)
                        System.out.println(countOfIterations + ":" + flag);

                    countOfIterations++;
                }
            }
        });

        Thread updatingReferenceThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    instance.a = new Object();
                }
            }
        });

        testingReferenceThread.start();
        updatingReferenceThread.start();
    }

}

这是我用来测试线程安全性的程序。

奇怪的行为

当我的程序在一些迭代之间开始时,我得到输出标志值,这意味着引用!=检查在相同的引用上失败。但是经过一些迭代后,输出变为常数值false,然后长时间执行程序不会生成单个true输出。
由于输出在一些n(不是固定的)迭代之后表明,输出似乎是恒定值,并且不会改变。
 输出:
对于一些迭代:

1494:true
1495:true
1496:true
19970:true
19972:true
19974:true
//after this there is not a single instance when the condition becomes true

回答:

在没有同步这个代码

Object a;

public boolean test() {
    return a != a;
}

可能会产生true。这是test()的字节码

    ALOAD 0
    GETFIELD test/Test1.a : Ljava/lang/Object;
    ALOAD 0
    GETFIELD test/Test1.a : Ljava/lang/Object;
    IF_ACMPEQ L1
...

因为我们可以看到它将字段a加载到局部var两次,它是一个非原子操作,如果a之间被另一个线程比较更改可能会产生false
此外,内存可见性问题在这里是相关的,不能保证当前线程对另一个线程所做的a的更改是可见的。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Is the != check thread safe?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

3 + 2 =