[英]Does ConcurrentHashMap make a copy of itself?
I recently attended an interview where the interviewer asked me question about HashMap
and ConcurrentHashMap
. 我最近参加了一次面试,面试官问我有关
HashMap
和ConcurrentHashMap
。 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. 关于您的问题的几点。
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. 由于这种行为,它可以在多线程上下文中抛出,但完全不依赖于此。
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.