集合上的线程安全迭代

我们都知道,当使用(例如)时,我们会得到底层集合的同步“视图”。Collections.synchronizedXXXsynchronizedSet()

但是,这些包装器生成方法的文档指出,在使用迭代器迭代集合时,我们必须显式同步集合。

您选择哪个选项来解决此问题?

我只能看到以下几种方法:

  1. 按照文档所述进行操作:在集合上同步
  2. 在调用之前克隆集合iterator()
  3. 使用迭代器是线程安全的集合(我只知道 /Set)CopyOnWriteArrayList

作为一个奖励问题:当使用同步视图时 - 使用foreach/Iterable线程安全吗?


答案 1

你已经真正回答了你的奖励问题:不,使用增强的for循环是不安全的 - 因为它使用迭代器。

至于哪种方法最合适 - 这实际上取决于您的上下文:

  • 写入非常不频繁吗?如果是这样,可能是最合适的。CopyOnWriteArrayList
  • 集合是否相当小,迭代速度很快?(即,您在循环中没有做太多工作)如果是这样,同步可能很好 - 特别是如果这种情况不会经常发生(即你不会对集合有太多的争用)。
  • 如果您正在做很多工作,并且不想阻止同时工作的其他线程,那么克隆集合的打击可能是可以接受的。

答案 2

取决于您的访问模型。如果并发性低且写入频繁,则 1 将具有最佳性能。如果具有高并发和不频繁写入,则 3 将具有最佳性能。选项2在几乎所有情况下都会表现不佳。

foreach调用 ,所以完全相同的东西适用。iterator()