我对Collection.synchronizedXXX
方法有疑问,他们返回基础集合的同步视图。
使用这些,我们必须手动同步迭代(例如here),否则可能会导致非确定性行为。
这究竟意味着什么?
我找到了另一句here:
面对并发访问时,用户必须在迭代时手动同步返回的集合。原因是迭代是通过对集合的多次调用来完成的,集合必须组成一个原子操作。
这就是我被困住的地方。我想如果我想修改集合,我会得到一个ConcurrentModificationException
。所以我需要进行同步以避免出现此异常(例如,由于编译器完成上下文切换,迭代被“暂停”)。
第二个链接有希望证实了我的想法。 “非确定性行为”句子怎么样?它是否反映了相同的想法(迭代暂停)或幕后有什么新东西?
答案 0 :(得分:1)
迭代是一个长期运行的操作。由Collection.synchronizedXXX
添加的逻辑会将next()
上的每个Iterator
电话视为单独的电话,这将是synchronized
,但您需要确保在您和{ #39;完全完成迭代。这就是为什么你必须在整个迭代过程中自己添加synchronized
块。
ConcurrentModificationException
,例如由ArrayList
抛出,不保证会被抛出:
请注意,迭代器的快速失败行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬性保证。失败快速的迭代器会尽最大努力抛出
ConcurrentModificationException
。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的故障快速行为应仅用于检测错误。
答案 1 :(得分:1)
迭代包括执行以下操作(直接或间接使用foreach循环):
while (iterator.hasNext()) {
iterator.next();
}
因此,如果在对hasNext()的调用和对next()的调用之间存在上下文切换,并且另一个线程从集合中删除元素,则最终会出现不可预测的行为:迭代器告诉您有一个下一个元素,实际上没有。您不是在列表的一致快照上进行迭代,而是在移动目标上进行迭代,并且在线程之间不共享的列表上永远不会发生异常。