Java ConcurrentHashMap在内部是如何工作的?

Java ConcurrentHashMap在内部是如何工作的?,java,collections,concurrency,hashmap,Java,Collections,Concurrency,Hashmap,我正在阅读有关Java并发性的Oracle官方文档,我想知道 public static <T> Collection<T> synchronizedCollection(Collection<T> c); 公共静态集合synchronizedCollection(集合c); 例如,使用 ConcurrentHashMap。我假设我在HashMap上使用synchronizedCollection(Collection c)。我知道,一般来说,同步集合本质

我正在阅读有关Java并发性的Oracle官方文档,我想知道

public static <T> Collection<T> synchronizedCollection(Collection<T> c);
公共静态集合synchronizedCollection(集合c);
例如,使用

ConcurrentHashMap
。我假设我在
HashMap
上使用
synchronizedCollection(Collection c)
。我知道,一般来说,同步集合本质上只是我的
HashMap
的装饰器,因此
ConcurrentHashMap
的内部显然有些不同。您有关于这些实施细节的一些信息吗

编辑:我意识到源代码是公开的:
synchronizedCollection()返回的对象是一个对象,其所有方法都在此对象上同步,因此此类包装器上的所有并发操作都是序列化的。ConcurrentHashMap是一个真正的并发容器,它具有细粒度的锁,优化了锁以尽可能降低争用。查看源代码,您将看到它的内部内容。

ConcurrentHashMap与
java.util.HashTable
类非常相似,只是
ConcurrentHashMap
提供了比
HashTable
synchronizedMap
更好的并发性
ConcurrentHashMap
在读取地图时不会锁定地图。此外,
ConcurrentHashMap
在写入时不会锁定整个
Map
。它仅在内部锁定正在写入的
映射的部分

另一个区别是,如果
ConcurrentHashMap
在迭代过程中发生更改,则ConcurrentHashMap不会抛出
ConcurrentModificationException
。虽然
迭代器
的设计不允许多个线程使用,但是
synchronizedMap
可能会抛出
ConcurrentModificationException
我会阅读,因为它的细节相当复杂。简言之,它已经做到了

  • 可以独立锁定的多个分区。(默认情况下为16)
  • 使用并发锁操作实现线程安全,而不是同步
  • 具有线程安全迭代器。synchronizedCollection的迭代器不是线程安全的
  • 不会暴露内部锁。synchronizedCollection没有

    • 这篇文章帮助我理解了它

      Hashtable提供对其条目的并发访问,但有一点需要注意,整个映射被锁定以执行任何类型的操作。 而这种开销在正常情况下在web应用程序中是可以忽略的 负载,在重负载下,可能导致响应时间延迟和 没有正当理由使服务器负担过重

      这就是ConcurrentHashMap的切入点。它们提供了所有的功能 Hashtable的性能几乎与HashMap一样好。 ConcurrentHashMap通过一个非常简单的机制来实现这一点。 集合维护的列表不是地图范围的锁,而是16个 默认情况下锁定,每个用于保护(或锁定)单个 一桶地图。这实际上意味着16个线程可以修改 在同一时间收集(只要他们都在工作 不同的桶)。事实上,没有通过此操作执行任何操作 锁定整个地图的集合。的并发级别 集合,可以同时修改它的线程数 没有阻塞,可以增加。然而,数字越高意味着更多 维护此锁列表的开销

      哈希表
      的“可伸缩性问题”在
      集合中以完全相同的方式出现。synchronizedMap(Map)
      -它们使用非常简单的同步,这意味着只有一个线程可以同时访问Map

      当您进行简单的插入和查找时,这不是什么大问题(除非您进行了非常密集的插入和查找),但当您需要迭代整个映射时,这会成为一个大问题,对于一个大型映射,这可能需要很长的时间-当一个线程执行此操作时,所有其他线程都必须等待,如果他们想要插入或查找任何内容


      ConcurrentHashMap
      使用非常复杂的技术来减少同步需求,允许多线程在不同步的情况下进行并行读取访问,更重要的是,它提供了一个不需要同步的迭代器,甚至允许在交互过程中修改映射(尽管它不能保证在迭代过程中插入的元素是否会被返回)。

      ConcurrentHashMap实现了提供并发性的ConcurrentMap。 Deep内部的迭代器设计为一次只能由一个线程使用,以保持同步。
      此映射在并发中被广泛使用。

      IMHO这是每个java开发人员都应该阅读的书籍之一:-)@PeterLawrey-seconded。投票赞成改正我也不明白他为什么投票反对你。我也投票支持你。为那些没有JDK的人提供一个到源代码的链接会很有用,IDE或谷歌访问我会添加一个链接。。)我刚刚意识到源代码对我来说是可用的。我看到CHM有自己的用于锁定的ReentrantLock子类。谢谢你的信息!是的,每个分区一个段。您可以增加分区的数量,但很少需要(除了一些微基准测试;)分区您指的是存储桶?或者这不是用经典的桶+链表模型实现的?链接已经失效,但是@LaurentBourgault Roy,cheers编辑的答案反映了这一点