简体   繁体   English

ConcurrentHashMap会自己复制吗?

[英]Does ConcurrentHashMap make a copy of itself?

I recently attended an interview where the interviewer asked me question about HashMap and ConcurrentHashMap . 我最近参加了一次面试,面试官问我有关HashMapConcurrentHashMap After the initial thread-safety benefits I said that it does not throw ConcurrentModificationException when it is being traversed as opposed to HashMap . 在获得最初的线程安全性好处之后,我说过,与HashMap相比,遍历它不会引发ConcurrentModificationException

The interviewer continued and asked me why it does not throw it. 面试官继续问我为什么不扔。 I said that internally HashMap has a variable modCount which keeps the number of modifications done to the map and Iterator is comparing this number against the one it's been initialised with at creation. 我说过, HashMap在内部有一个变量modCount ,该变量保留对映射所做的修改次数,并且Iterator将此数字与创建时已初始化的数字进行比较。 If this number is different it will throw an exception and this comparison does not happen for ConcurrentHashMap . 如果此数字不同,则将引发异常,并且ConcurrentHashMap不会进行此比较。

He then said ConcurrentHashMap will make a copy of itself when traversing. 然后,他说ConcurrentHashMap会在遍历时复制其自身。

I have doubts about this statement since haven't come across this before. 我对此声明表示怀疑,因为之前从未遇到过。 Even reading the documentation does not give me a sufficient answer. 即使阅读文档也无法给我足够的答案。

Would it make at any point a copy (read or write)? 它会在任何时候复制(读或写)吗?

No it has nothing to do with making a copy of anything. 不,它与复制任何内容无关。 And no throwing ConcurrentModificationException isn't necessarily under multi-threading environment. 在多线程环境下,不一定抛出ConcurrentModificationException异常。

Several points regarding to your questions. 关于您的问题的几点。

  1. ConcurrentModificationException has nothing to do with concurrency (and it actually has a bad name). ConcurrentModificationException与并发无关(它实际上有一个不好的名字)。 It's thrown when you are iterating through some data structure and you use the iterator again after making some modification to the structure. 当您遍历某些数据结构并在对该结构进行了一些修改之后再次使用迭代器时,将引发该错误。 This is called fail fast behavior. 这称为fail fast行为。 Due to such behavior it can be thrown under multi-threading context but has no dependency to that at all. 由于这种行为,它可以在多线程上下文中抛出,但完全不依赖于此。

  2. ConcurrentHashMap is a delicated structure and I recommend you to read through it. ConcurrentHashMap是一个精细的结构,我建议您通读它。 The way it achieve concurrency is by 它实现并发的方式是

    • Any threads accessing different buckets in the map are naturally separated so no need to synchronize between them except for rehashing case. 访问映射中不同存储桶的所有线程自然都被分隔开,因此,除了重新哈希大小写外,无需在它们之间进行同步。

    • For the threads accessing the same bucket, if the bucket is empty it uses CAS ie AtomicReference to access the only element in the bucket. 对于访问同一存储桶的线程,如果存储桶为空,则使用CAS即AtomicReference来访问存储桶中的唯一元素。

    • In case the bucket under operation has hash collision and has multiple elements, its kept as a linked list (except for the case of JDK 1.8 which reworks the link list into a binary tree to achieve better performance under extreme hash collision). 如果正在操作的存储桶发生哈希冲突并具有多个元素,则将其保存为链接列表(JDK 1.8除外,该示例将链接列表重新构建为二叉树以在极端哈希冲突下获得更好的性能)。 The benefit of a linked list is it supports concurrency naturally as long as you operate on the next pointer in CAS way. 链接列表的好处是,只要您以CAS方式对下一个指针进行操作,它就自然支持并发。

There are still a lot of coding art in the ConcurrentHashMap so I suggest you to read its source code thoroughly. ConcurrentHashMap中仍然有很多编码ConcurrentHashMap所以我建议您仔细阅读其源代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM