java - != 检查线程安全吗?

标签 java multithreading thread-safety atomic race-condition

我知道像 i++ 这样的复合操作不是线程安全的,因为它们涉及 多个 操作。

但是检查引用本身是线程安全的操作吗?

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 加载到本地变量两次,这是一个非原子操作,如果 a 在两者之间被另一个线程更改,则比较可能会产生

此外,内存可见性问题与此处有关,不能保证另一个线程对 a 所做的更改将对当前线程可见。

关于java - != 检查线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18460580/

相关文章:

java - 如何在图形中以透明颜色制作矩形?

java - 我在这些类中使用 Bitmap 是否有效

c# - 是否可以同时使用线程并发和并行?

ios - +(void) 初始化线程安全

java - Android 上的 Facebook 集成 fbconnect 断开的链接

java - 非常奇怪的NoClassDefFoundError

multithreading - 使用 MVar 在 Haskell 中创建线程安全队列(也许?)

c++ - 线程的内存问题

android - Android应用程序中的线程安全?

java - 当我在 arrayList 中使用 .get() 方法打印对象时,如何防止打印哈希码?