我正在阅读关于Java中的并发的官方Oracle文档,我想知道
返回的Collection
之间有什么区别?
public static <T> Collection<T> synchronizedCollection(Collection<T> c);
并使用例如
ConcurrentHashMap
。我假设我在synchronizedCollection(Collection<T> c)
上使用HashMap
。我知道一般来说,同步集合本质上只是我HashMap
的装饰器所以很明显ConcurrentHashMap
的内部结构有所不同。您是否有关于这些实施细节的信息?
编辑:我意识到源代码是公开的: ConcurrentHashMap.java
答案 0 :(得分:42)
我会阅读source of ConcurrentHashMap因为它在细节上相当复杂。简而言之,它有
答案 1 :(得分:22)
ConcurrentHashMap
与java.util.HashTable
类非常相似,只是ConcurrentHashMap
提供比HashTable
或synchronizedMap
更好的并发性。在您阅读地图时,ConcurrentHashMap
不会锁定地图。此外,ConcurrentHashMap
在写入时不会锁定整个Map
。它只在内部锁定正在写入的Map
部分。
另一个区别是,如果在迭代时更改ConcurrentModificationException
,则ConcurrentHashMap不会抛出ConcurrentHashMap
。 Iterator
并非设计为由多个线程使用,而synchronizedMap
可能会抛出ConcurrentModificationException
答案 2 :(得分:15)
这篇文章帮我理解了Why ConcurrentHashMap is better than Hashtable and just as good as a HashMap
Hashtable提供对其条目的并发访问,只需要一个小小的警告,整个地图都被锁定以执行任何类型的操作。 虽然这种开销在正常的Web应用程序中是可忽略的 负载,在重负载下,它可能导致延迟响应时间和 无缘无故地过度使用你的服务器。
这是ConcurrentHashMap的步骤。它们提供了所有功能 Hashtable的表现几乎和HashMap一样好。 ConcurrentHashMap通过一种非常简单的机制实现了这一目标。 该集合不是地图宽锁,而是维护16的列表 默认情况下,每个锁都用于保护(或锁定)单个锁 地图桶。这实际上意味着16个线程可以修改 一次性收集(只要他们都在努力 不同的水桶)。事实上,没有执行此操作 锁定整个地图的集合。并发级别 集合,可以同时修改它的线程数 没有阻塞,可以增加。然而,更高的数字意味着更多 维护这个锁列表的开销。
答案 3 :(得分:5)
Hashtable
中的“可伸缩性问题”在Collections.synchronizedMap(Map)
中以完全相同的方式出现 - 它们使用非常简单的同步,这意味着只有一个线程可以同时访问地图。 / p>
当您进行简单的插入和查找时(除非您非常密集地执行此操作),这不是什么大问题,但是当您需要遍历整个Map时会成为一个大问题,这可能需要很长时间才能完成映射 - 当一个线程执行此操作时,所有其他线程必须等待,如果他们想要插入或查找任何内容。
ConcurrentHashMap
使用非常复杂的技术来减少同步的需要,并允许多个线程进行并行读取访问而不进行同步,更重要的是,提供了一个不需要同步的迭代器,甚至允许在过程中修改Map。 interation(虽然它不能保证是否会返回在迭代期间插入的元素)。
答案 4 :(得分:4)
由 synchronizedCollection()返回的是一个对象,其所有方法都在 this 上同步,因此对此类包装器的所有并发操作都是序列化的。 ConcurrentHashMap是一个真正的并发容器,具有优化的细粒度锁定,以尽可能降低争用。看看源代码,你会看到里面的内容。
答案 5 :(得分:0)
ConcurrentHashMap实现提供并发性的ConcurrentMap。 在内部,它的迭代器设计为一次只能由一个线程使用,以保持同步。 该地图在并发方面得到了广泛使用。