concurrntHashMap 能同时保证真正的线程安全和并发吗?
我们知道ConcurrentHashMap可以提供多线程并发访问来提高性能,并且在这个类中,段是同步的(我说得对吗?)。问题是,这样的设计能保证线程安全吗?假设我们有 30 多个线程访问和更改 ConcurrentHashMap 实例中由同一键映射的对象,我的猜测是,它们仍然需要为此排队,不是吗?
我记得《Java并发实践》一书中说ConcurrentHashMap提供了并发读取和相当水平的并发写入。在上述场景中,如果我的猜测是正确的,那么性能不会比使用 Collection 的静态同步包装器 api 更好吗?
感谢您的澄清, 约翰
We know that ConcurrentHashMap can provide concurrent access to multiple threads to boost performance , and inside this class, segments are synchronized up (am I right?). Question is, can this design guarantee the thread safety? Say we have 30+ threads accessing &changing an object mapped by the same key in a ConcurrentHashMap instance, my guess is, they still have to line up for that, don't they?
From my recollection that the book "Java Concurrency in Practice" says the ConcurrentHashMap provide concurrent reading and a decent level of concurrent writing. in the aforementioned scenario, and if my guess is correct, the performance won't be better than using the Collection's static synchonization wrapper api?
Thanks for clarifying,
John
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您仍然必须同步对正在修改的对象的任何访问,并且您怀疑对同一密钥的所有访问仍然会存在争用。性能的改进来自于对不同密钥的访问,这当然是更典型的情况。
You will still have to synchronize any access to the object being modified, and as you suspect all access to the same key will still have contention. The performance improvement comes in access to different keys, which is of course the more typical case.
ConcurrentMap
可以为您提供的并发性是,对映射本身的修改是以原子方式完成的,并且任何写入发生在任何读取之前(这一点很重要,因为它提供了安全发布地图中的任何引用 安全发布意味着从地图中检索的任何(可变)对象在放入地图之前都将可见。帮助发布修改但是
,如果您有被多方修改的可变对象,那么并发性和线程安全性通常很难推理和纠正,通常您必须锁定才能获得正确的结果。通常将不可变对象与 ConcurrentMap 条件 putIfAbsent/replace 方法结合使用,并以这种方式线性化您的算法。这种无锁风格往往更容易推理。
All a
ConcurrentMap
can give you wrt to concurrency is that modifications to the map itself are done atomically, and that any writes happen-before any reads (this is important as it provides safe publishing of any reference from the map.Safe-publishing means that any (mutable) object retrieved from the map will be seen with all writes to it before it was placed in the map. It won't help for publishing modifications that are made after retrieving it though.
However, concurrency and thread-safety is generally hard to reason about and make correct if you have mutable objects that are being modified by multiple parties. Usually you have to lock in order to get it right. A better approach is often to use immutable objects in conjunction with the
ConcurrentMap
conditional putIfAbsent/replace methods and linearize your algorithm that way. This lock-free style tends to be easier to reason about.保证了map的线程安全;即,在存在同时执行更新的多个线程的情况下,地图上的访问和更新具有明确定义且有序的行为。
它确实保证了键或值对象的线程安全。并且它不提供任何形式的更高级别的同步。
如果您有多个线程尝试使用相同的密钥,那么它们的操作将不可避免地在某种程度上被序列化。这是不可避免的。
事实上,从简要查看源代码来看,如果映射的特定段存在太多争用,ConcurrentHashMap 看起来会回退到使用传统锁。如果您有多个线程尝试同时访问和更新同一个密钥,则会触发锁定。
It guarantees the thread safety of the map; i.e. that access and updates on the map have a well defined and orderly behaviour in the presence of multiple threads performing updates simultaneously.
It does guarantee thread safety of the key or value objects. And it does not provide any form of higher level synchronization.
If you have multiple threads trying to use the same key, then their operations will inevitably be serialized to some degree. That is unavoidable.
In fact, from briefly looking at the source code, it looks like
ConcurrentHashMap
falls back to using conventional locks if there is too much contention for a particular segment of the map. And if you have multiple threads trying to access AND update the same key simultaneously, that will trigger locking.首先请记住,线程安全工具并不能保证其本身的线程安全使用 putIfAbsent
的
if(!map.contains(k))map.put(k,v);
构造例如,不是线程安全的,每个值访问/修改仍然必须独立地实现线程安全
first remember that a thread safe tool doesn't guarantee thread safe usage of it in and of itself
the
if(!map.contains(k))map.put(k,v);
construct to putIfAbsent for example is not thread safeand each value access/modification still has to be made thread safe independently
即使对于相同的键,读取也是并发的,因此对于典型应用程序来说性能会更好。
Reads are concurrent, even for the same key, so performance will be better for typical applications.