对于不同的键,HashMap 线程安全吗? [英] Is a HashMap thread-safe for different keys?

查看:26
本文介绍了对于不同的键,HashMap 线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有两个多线程访问一个 HashMap,但保证它们永远不会同时访问同一个键,那还会导致竞争条件吗?

If I have two multiple threads accessing a HashMap, but guarantee that they'll never be accessing the same key at the same time, could that still lead to a race condition?

推荐答案

在@dotsid 的回答中,他是这样说的:

In @dotsid's answer he says this:

如果您以任何方式更改 HashMap,那么您的代码就会被破坏.

If you change a HashMap in any way then your code is simply broken.

他是对的.如果线程使用不相交的键集,则在没有同步的情况下更新的 HashMap 将破坏偶数.以下是部分1可能出错的事情.

He is correct. A HashMap that is updated without synchronization will break even if the threads are using disjoint sets of keys. Here are just some1 of the things that can go wrong.

  • 如果一个线程执行了 put,那么另一个线程可能会看到哈希图大小的过时值.

  • If one thread does a put, then another thread may see a stale value for the hashmap's size.

当一个线程执行触发表重建的 put 时,另一个线程可能会看到哈希表数组引用的临时或陈旧版本、其大小、其内容或哈希链.可能会出现混乱.

When a thread does a put that triggers a rebuild of the table, another thread may see transient or stale versions of the hashtable array reference, its size, its contents or the hash chains. Chaos may ensue.

当一个线程对一个与其他线程使用的某个键发生冲突的键执行 put 时,后一个线程对其键执行 put,那么后者可能会看到哈希链引用的陈旧副本.可能会出现混乱.

When a thread does a put for a key that collides with some key used by some other thread, and the latter thread does a put for its key, then the latter might see a stale copy of hash chain reference. Chaos may ensue.

当一个线程使用与其他线程的其中一个键冲突的键来探测表时,它可能会在链上遇到该键.它将对该键调用 equals,如果线程未同步,则 equals 方法可能会在该键中遇到陈旧状态.

When one thread probes the table with a key that collides with one of some other thread's keys, it may encounter that key on the chain. It will call equals on that key, and if the threads are not synchronized, the equals method may encounter stale state in that key.

如果您有两个线程同时执行 putremove 请求,则存在大量竞争条件.

And if you have two threads simultaneously doing put or remove requests, there are numerous opportunities for race conditions.

我能想到三个解决方案:

I can think of three solutions:

  1. 使用ConcurrentHashMap.
  2. 使用常规的HashMap,但在外部同步;例如使用原始互斥锁、Lock 对象等.
  3. 为每个线程使用不同的 HashMap.如果线程真的有一组不相交的键,那么它们就不需要(从算法的角度来看)共享一个 Map.事实上,如果您的算法涉及在某个时刻迭代映射的键、值或条目的线程,那么将单个映射拆分为多个映射可以显着提高该部分的处理速度.
  1. Use a ConcurrentHashMap.
  2. Use a regular HashMap but synchronize on the outside; e.g. using primitive mutexes, Lock objects, etcetera.
  3. Use a different HashMap for each thread. If the threads really have a disjoint set of keys, then there should be no need (from an algorithmic perspective) for them to share a single Map. Indeed, if your algorithms involve the threads iterating the keys, values or entries of the map at some point, splitting the single map into multiple maps could give a significant speedup for that part of the processing.


1 - 我们无法列举所有可能出错的事情.首先,我们无法预测所有 JVM 将如何处理 JMM 的未指定方面......在所有平台上.但无论如何你都不应该依赖这种信息.您需要知道的是,像这样使用 HashMap 从根本上是错误的.执行此操作的应用程序已损坏...即使您还没有观察到症状...


1 - We cannot enumerate all of the possible things that could go wrong. For a start, we can't predict how all JVMs will handle the unspecified aspects of the JMM ... on all platforms. But you should NOT be relying on that kind of information anyway. All you need to know is that it is fundamentally wrong to use a HashMap like this. An application that does this is broken ... even if you haven't observed the symptoms ... yet.

这篇关于对于不同的键,HashMap 线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆