Java ArrayList.add() 方法线程安全,用于纯并行添加



考虑一个函数上的for循环,该函数接受ArrayList引用并将对象添加到该ArrayList。我现在想并行执行每个函数调用。

如果我不关心添加对象的顺序并且没有函数读取或操作任何 ArrayList 元素,那么 ArrayList.add() 方法线程是否安全?所以我只想确保在并行调用结束时将所有对象添加到列表中。

不,它不是线程安全的。使用 Collections.synchronizedList() 包装列表,或在访问列表时使用显式同步。

ArrayList.add()不是

线程安全的。即使您没有从其他线程读取列表,也不应依赖此逻辑假设。以下是ArrayList.add()的定义:

public boolean add(E e) {
    ensureCapacity(size + 1);
    elementData[size++] = e;
    return true;
}

作为在没有同步的情况下可能出现的问题的示例,添加所有元素后,size属性可能不一致。如果稍后尝试获取元素数,则结果可能不正确。

为此,您可以使用CopyOnWriteArrayList ArrayList因为线程不安全。

CopyOnWriteArrayList

编辑:我只是要引用 Oracle 来向您展示这是您所需要的:

ArrayList 的线程安全变体,其中所有可变操作(添加、设置等)都是通过创建基础数组的新副本来实现的。 这通常成本太高,但当遍历操作数量远远超过突变时,这可能比替代方法更有效,并且当您不能或不想同步遍历,但需要排除并发线程之间的干扰时,这很有用。

否,add 方法使用许多没有线程安全控制的类级属性。在多个线程中并发调用 add() 极有可能导致问题。

不,它不是线程安全的。您有两种选择:

  1. 使用其他集合:CopyOnWriteArrayList
  2. 在多线程环境中修改数组列表时使用显式同步。

它不是线程安全的。在没有同步的情况下,线程可能会践踏彼此对列表的修改,甚至可能看不到彼此对列表的更改。无论哪种方式,它都会被损坏。

您应该首先使用Collections.synchronizedList或围绕 add 调用的同步语句使代码正常工作。

如果您发现每个操作的同步开销太大,下一个替代方法是为每个线程提供自己的私有 ArrayList,然后定期或最后将私有 ArrayList 的内容转储到主 ArrayList 中。

最新更新