Collection.stream()是否具有内部同步?

Gen*_*zer 5 java multithreading java-stream

我一直在尝试重现(并解决)ConcurrentModificationException当一个实例HashMap被多个Threads 读取和写入时.

免责声明:我知道这HashMap不是线程安全的.

在以下代码中:

import java.util.*;

public class MyClass {

    public static void main(String args[]) throws Exception {
        java.util.Map<String, Integer> oops = new java.util.HashMap<>();
        oops.put("1", 1);
        oops.put("2", 2);
        oops.put("3", 3);

        Runnable read = () -> {
            System.out.println("Entered read thread");

            /*
             * ConcurrentModificationException possibly occurs
             *
            for (int i = 0; i < 100; i++) {
                List<Integer> numbers = new ArrayList<>();
                numbers.addAll(oops.values());
                System.out.println("Size " + numbers.size());
            }
            */

            for (int i = 0; i < 100; i++) {
                List<Integer> numbers = new ArrayList<>();
                numbers.addAll(oops.values()
                        .stream()
                        .collect(java.util.stream.Collectors.toList()));
                System.out.println("Size " + numbers.size());
            }
        };

        Runnable write = () -> {
            System.out.println("Entered write thread");
            for (int i = 0; i < 100; i++) {
                System.out.println("Put " + i);
                oops.put(Integer.toString(i), i);
            }
        };

        Thread writeThread = new Thread(write, "write-thread");
        Thread readThread = new Thread(read, "read-thread");

        readThread.start();
        writeThread.start();

        readThread.join();
        writeThread.join();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我创建了两个线程:一个继续将元素放入a HashMap,另一个是迭代HashMap.values().

read线程中,如果我正在使用numbers.addAll(oops.values()),ConcurrentModificationException随机发生.虽然线条按预期随机打印.

但是,如果我切换到numbers.addAll(oops.values().stream()..,我不会得到任何错误.但是,我发现了一个奇怪的现象.由所有的行read线被印刷由印刷线write螺纹.

我的问题是,确实Collection.stream()有某种内部同步?

更新:

使用JDoodle https://www.jdoodle.com/a/IYy,在JDK9和JDK10上,我会得到ConcurrentModificationException预期的结果.

谢谢!

Eug*_*ene 1

你所看到的一切绝对是偶然的;请记住,内部System.out.println执行 a synchronzied; 因此,可能会以某种方式使结果看起来按顺序出现。

我没有太深入地研究你的代码 - 因为分析 Why HashMap,这不是线程安全的,是 miss 行为很可能是徒劳的;如您所知,它被记录为非线程安全的。

关于这一点ConcurrentModificationException,文档明确表示它将尽力抛出该问题;所以要么是java-8在这一点上较弱,要么这又是偶然的。