繁体   English   中英

Java 数组线程安全吗?

[英]Are Java arrays thread safe?

像标题一样,给定 2 个数组int[] a , int[] b由两个线程共享,每个线程重新排列两个数组的元素,使第一个数组的每个元素<=第二个数组的对应元素数组a[i] <= b[i]输出似乎总是正确的,不需要同步

public class MyClass {

    int[] a = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    int[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    class MyThread extends Thread {
        public void run() {
                for (int i = 0; i < a.length; i++) {
                    if (a[i] > b[i]) {
                        int temp = b[i];
                        b[i] = a[i];
                        a[i] = temp;
                    }
                }
        }
    }

    public static void main(String[] args) {

        MyClass myClass = new MyClass();

        MyThread t1 = myClass.new MyThread();
        MyThread t2 = myClass.new MyThread();

        t1.start();
        t2.start();

        while (t1.isAlive() | t2.isAlive()) {
            System.out.println("waiting");
        }

        System.out.println(Arrays.toString(myClass.a));
        System.out.println(Arrays.toString(myClass.b));
    }
}

这是我得到的输出(多次运行)我应该认为这只是运气还是我遗漏了什么?

a = [0, 1, 2, 3, 4, 4, 3, 2, 1, 0]
b = [9, 8, 7, 6, 5, 5, 6, 7, 8, 9]

这是运气。 除非线程以某种方式同步,否则不能保证一个线程的写入对其他线程可见。 数组也不例外。

这里有一个AtomicIntegerArray类型可以帮助你。

虽然将数组字段声明为volatile不会扩展到数组的元素,但可能有一种方法可以使用它建立先发生关系。 我必须仔细考虑一下,但如果它确实有效,从某种意义上说,它会相当脆弱,因为稍微改变用法可能会产生并发错误。

不,他们不是。 线程将按照他们想要的方式修改它们,并且有可能出现竞争条件。 如果您希望一次有 1 个以上的线程对一个集合进行操作,则需要使用特殊的线程安全集合,这些集合内置了同步功能,因此您不必担心

您的输出看起来正确的原因是因为这种竞争条件发生的可能性很小。 你不能用单元测试来保护它。 你需要做一些分析工作来证明你的代码是线程安全的,或者使用一个特殊的框架来测试多线程的东西。

这回答了你的问题了吗 ? 在评论中给我一个回复

不,数组不是线程安全的。 从某种意义上说,这是幸运的,因为它是由于您不知道的保证而起作用的。

在 JLS 中:

线程 T1 中的最终操作与另一个线程 T2 中检测到 T1 已终止的任何操作同步。

找到线程因 isAlive 死亡计数为此。 同步与创建一个发生在之前的关系,并确保对数组的更改对主线程可见。 两个线程之间存在数据竞争,但它们在做同样的事情,并且更改的应用顺序无关紧要,因此结果是可以预测的。

有时代码只是偶然地工作,因为某些事情导致了先发生关系,然后那个东西被删除了,东西神秘地破坏了。 删除对 System.out.println 的调用就是一个例子,该调用获取了一个锁,最终使一些更改可见,然后有人删除了 println 并惊讶地发现它不再起作用了。 看到这个问题:循环没有看到没有打印语句的其他线程改变的值

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM