ConcurrentHashMap 会复制自己吗?

Does ConcurrentHashMap make a copy of itself?

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

面试官继续问我为什么不扔。我说过 HashMap 内部有一个变量 modCount,它保持对地图所做的修改次数,Iterator 将这个数字与创建时初始化的数字进行比较。如果这个数字不同,它将抛出异常,并且 ConcurrentHashMap.

不会发生这种比较

然后他说ConcurrentHashMap遍历的时候会自己复制一份

我对这个说法有疑问,因为以前没有遇到过这个。即使阅读文档也不能给我足够的答案。

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

不,它与复制任何内容无关。而no throwingConcurrentModificationException不一定是在多线程环境下。

关于你的问题的几点。

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

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

    • 访问映射中不同桶的任何线程自然分离,因此除了重新散列情况外不需要在它们之间同步。

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

    • 如果正在操作的桶有散列冲突并且有多个元素,它被保存为一个linked列表(除了JDK 1.8的情况,它重新处理了link 将列表转换为二叉树以在极端哈希冲突下获得更好的性能)。 linked 列表的好处是它自然支持并发,只要你以 CAS 方式操作 next 指针。

ConcurrentHashMap里面还是有很多编码艺术的,所以建议大家仔细阅读它的源代码。