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

查看:23
本文介绍了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 将破坏 even.以下是只是一些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 的 unspecified 方面.但是无论如何,您都不应该依赖此类信息.你需要知道的是,像这样使用 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天全站免登陆