【发布时间】:2014-11-14 11:13:40
【问题描述】:
我昨天了解到,多年来我一直在错误地使用具有并发性的集合。
每当我创建一个需要由多个线程访问的集合时,我都会将它包装在 Collections.synchronized* 方法之一中。然后,每当 mutating 集合时,我也会将它包装在一个同步块中(我不知道我为什么要这样做,我一定以为我在某处读过它)。
但是,在更仔细地阅读 API 之后,似乎您在 迭代 集合时需要同步块。来自 API 文档(用于地图):
当迭代任何集合视图时,用户必须在返回的地图上手动同步:
这是一个小例子:
List<O> list = Collections.synchronizedList(new ArrayList<O>());
...
synchronized(list) {
for(O o: list) { ... }
}
所以,鉴于此,我有两个问题:
为什么这甚至是必要的?我能想到的唯一解释是他们使用默认迭代器而不是托管线程安全迭代器,但他们本可以创建一个线程安全迭代器并修复这个混乱,对吧?
更重要的是,这是为了什么?通过将迭代放在同步块中,您可以防止多个线程同时迭代。但是另一个线程可能会在迭代时改变列表,那么同步块如何帮助呢?无论是否同步,都不会在其他地方改变列表与迭代有关吗?我错过了什么?
感谢您的帮助!
【问题讨论】:
-
我已回滚您最近的编辑。请不要编辑问题以将答案包含在其中。让问题成为问题,让答案成为答案。
-
@chris-hayes:罗杰!
标签: java collections concurrency