java - 同步ArrayList并发写入

标签 java multithreading collections arraylist

大家。为了测试 Collections.synchronizedList() 方法返回的 ArrayList,我定义了一个静态类,如下所示。

static class ListWriter implements Runnable { 
    private List<Integer> list; 

    public ListWriter(List<Integer> list) { 
        this.list = list; 
    } 

    public void run() {  // I didn't use synchronized(list) {} block here.
        try { 
            for (int i = 0; i < 20; i++) { 
                list.add(i); 
                Thread.sleep(10); 
            } 
        } catch (Exception e) { 
            e.printStackTrace();
        }
    } 
} 

以及测试方法如下

private static void test1() throws Exception {
    List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
    Thread t1 = new Thread(new ListWriter(list)); 
    Thread t2 = new Thread(new ListWriter(list));

    t1.start(); 
    t2.start(); 
    t1.join(); 
    t2.join(); 
    for (int i = 0; i < list.size(); ++i) { 
        System.out.println(list.get(i)); 
    } 
}

结果通常是这样的: 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 号 17 号 18 18 19 19

但有时会是这样的:

0 0 1 1 2 3 2 3 4 5 4 5 6 7 6 8 7 9 8 10 9 11 10 12 11 13 12 14 13 15 14 15 16 17 号 16 17 号 18 19 18 19

这些结果是否表明该进程是线程安全的? 关键是我没有在写入线程中使用同步块(synchronized block),这是迭代 Collection.synchronizedList() 方法返回的同步 ArrayList 时明确需要的。那么你认为该进程是线程安全的还是我仍然需要使用同步块(synchronized block)?

最佳答案

输出是不确定的 - 它取决于底层操作系统的调度行为。
事实上,有时你得到某个序列只是一个巧合。 您的列表在创建时由 Collections.synchronizedList 进行同步,因此您不需要任何额外的同步。

对列表线程安全性的粗略测试是在两个线程完成后验证列表中包含的元素数量是否等于 40。

正如您所指出的,对于并发读取,您需要在返回的列表上进行同步,如 the documentation 中所述。

关于java - 同步ArrayList并发写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11863821/

相关文章:

java - 模拟器崩溃 "Invalid int"

python - Matplotlib:在多个线程中同时绘图

java - 任何计算机(多核或单核)都可以同时运行多个线程吗

c++ - 如何在pthread线程中创建memcpy?

java - 对 List 集合中的对象使用 Contains

Java负载均衡Tcp代理服务器设计

java - Cassandra一致性(节点离线时)

java - Eclipse 插件内的图像路径

java - 为什么我们需要HashMap以外的数据结构

java - 类型中的方法 func(List<Object>) 不适用于参数 (List<String>)