java - ConcurrentHashMap 是否会复制自身?

标签 java concurrency hashmap concurrenthashmap

我最近参加了一次面试,面试官问了我有关 HashMapConcurrentHashMap 的问题。在最初的线程安全优势之后,我说过与 HashMap 相比,它在遍历时不会抛出 ConcurrentModificationException

面试官继续问我为什么不扔。我说过,HashMap 内部有一个变量 modCount,它保存对映射所做的修改数量,而 Iterator 将此数字与其实际值进行比较在创建时已初始化。如果此数字不同,则会引发异常,并且 ConcurrentHashMap 不会发生此比较。

然后他说 ConcurrentHashMap 在遍历时会复制自身。

我对这个说法表示怀疑,因为以前没有遇到过这种情况。即使阅读文档也没有给我足够的答案。

它会在任何时候制作副本(读或写)吗?

最佳答案

不,它与复制任何东西无关。并且在多线程环境下不一定会抛出ConcurrentModificationException

关于您的问题的几点。

  1. ConcurrentModificationException 与并发性无关(而且它实际上有一个坏名字)。当您迭代某些数据结构并且在对该结构进行一些修改后再次使用迭代器时,会抛出该错误。这称为快速失败行为。由于这种行为,它可以在多线程上下文中抛出,但对此完全没有依赖性。

  2. ConcurrentHashMap是一个精致的结构,我建议你仔细阅读它。它实现并发的方式是通过

    • 任何访问映射中不同存储桶的线程都是自然分离的,因此除了重新哈希情况之外不需要在它们之间进行同步。

    • 对于访问同一个存储桶的线程,如果存储桶为空,则使用 CAS,即 AtomicReference 来访问存储桶中的唯一元素。

    • 如果操作中的桶发生哈希冲突且有多个元素,则将其保留为链表(JDK 1.8 的情况除外,它将链表重新改造为二叉树,以在极端哈希下获得更好的性能碰撞)。链表的好处就是只要用CAS方式操作next指针就天然支持并发。

ConcurrentHashMap 中还有很多编码艺术,因此我建议您仔细阅读其源代码。

关于java - ConcurrentHashMap 是否会复制自身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34039366/

相关文章:

java - 构建失败 - gradle

java - 最佳跨平台 GUI 和 USB 语言

java - Spring H2 嵌入式数据库

javascript - 如何在没有冲突的 Node 中创建 tmp 目录

java - Threadpool 如何重用线程以及它是如何工作的

java - 在 Java 中使用 Hashmap 是否可以打印出具有相同值的键的数量?

java - 如何从 Java 干净地启动和停止 Tomcat,为什么我的方法不能重复工作?

java - 通过不同线程同时读取和更改变量

java - 在 hashmap 中,使用就地对象实例化设置自定义对象值

java - HashMap 方法将其用作最常见的值