ArrayList构造函数的线程安全性
我正在看这段代码。 这个构造函数委托给本地方法“System.arraycopy”
线程安全吗? 我的意思是它可以抛出一个ConcurrentModificationException?
public Collection<Object> getConnections(Collection<Object> someCollection) {
return new ArrayList<Object>(someCollection);
}
如果要复制的集合是ThreadSafe,例如CopyOnWriteArrayList,它有什么区别吗?
public Collection<Object> getConnections(CopyOnWriteArrayList<Object> someCollection) {
return new ArrayList<Object>(someCollection);
}
编辑:我知道ThreadSafe!= ConcurrentModificationException。 我试图在某个时间点对数据进行快照。 因此,如果另一个线程通过拷贝中途写入someCollection,我不在乎结果是否有新对象。 我只是不希望它抛出ConcurrentModificationException或更糟
你的问题是你是否可以安全地使用new ArrayList<Foo>(thatCollection)
获取可能正在由另一个线程进行并发修改的集合的快照。 答案是:只要thatCollection
本身是线程安全的,是的。 因此,如果它是CopyOnWriteArrayList
, synchronizedList
或Vector
,如果它不是线程安全的,例如,如果它是另一个ArrayList
,那么你不好。 (会发生什么情况可能比ConcurrentModificationException
更糟糕。)
原因是ArrayList
构造函数只对其他集合进行单个原子调用 - 对其toArray
方法。 所以它基本上享有该方法本身具有的任何线程安全保证。 它并不总是这样实施,但现在正是因为这个原因。 我们用ImmutableList.copyOf
在Guava中做同样的事情。
这个构造函数委托给本地方法“System.arraycopy”
实际上,它在someCollection
上调用了someCollection
toArray()
。 如果someCollection
是一个ArrayList
那最终会调用System.arraycopy
。 对于其他集合类型,数组将以其他方式创建。
线程安全吗?
没有。
我的意思是它可以抛出一个ConcurrentModificationException?
如果它是一个ArrayList
它不会抛出ConcurrentModificationException
...但是这不会使它线程安全!
例如,如果一个不同的线程在您的线程调用此构造函数时在someCollection
上调用set(obj, pos)
,那么新创建的ArrayList
的内容是不可预知的。
线程安全和ConcurrentModificationException是不同的概念。 线程安全对象是多线程可以同时调用其方法的对象,并且保证对象中的数据不会受到损坏(例如:http://thejavacodemonkey.blogspot.com/2007/08/making-您的Java类线程safe.html)。 例如,当您正在迭代集合并且集合发生更改时,会发生ConcurrentModificationException。 更改可能来自不同的线程或同一个线程。
在构造函数中,如果另一个线程在构造函数复制时更改someCollection
,则可能导致未定义的行为(例如,新集合中的数据损坏,因为集合不是线程安全的)或ConcurrentModificationException(如果集合的确如此检测并发修改,但这并不能保证,因为它不是线程安全的...... :-)
如果您的构造函数要使用Collection<Object>
,则需要确保其他线程在构造函数返回之前不会修改该集合。
另一方面,CopyOnWriteArrayList是线程安全的并且保证不会抛出ConcurrentModificationException,因此您应该以这种方式安全地执行此操作,而无需编写额外的同步代码。
链接地址: http://www.djcxy.com/p/66515.html