考虑一个函数上的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() 极有可能导致问题。
不,它不是线程安全的。您有两种选择:
- 使用其他集合:
CopyOnWriteArrayList
- 在多线程环境中修改数组列表时使用显式同步。
它不是线程安全的。在没有同步的情况下,线程可能会践踏彼此对列表的修改,甚至可能看不到彼此对列表的更改。无论哪种方式,它都会被损坏。
您应该首先使用Collections.synchronizedList
或围绕 add 调用的同步语句使代码正常工作。
如果您发现每个操作的同步开销太大,下一个替代方法是为每个线程提供自己的私有 ArrayList,然后定期或最后将私有 ArrayList 的内容转储到主 ArrayList 中。