一尘不染

HashMap对于不同的密钥是线程安全的吗?

java

如果我有两个多个线程访问HashMap,但要保证它们永远不会同时访问同一密钥,那是否还会导致争用情况?


阅读 341

收藏
2020-03-21

共1个答案

一尘不染

在@dotsid的回答中,他说:

如果你以任何方式更改HashMap,则代码将被破坏。

他是正确的。即使线程使用的是不相交的键集,在没有同步的情况下更新的HashMap也会中断。这是一些可能出错的事情。

  • 如果一个线程执行put,则另一线程可能会看到哈希图大小的陈旧值。

  • 当一个线程执行put触发表重建的操作时,另一个线程可能会看到哈希表数组引用的瞬时或陈旧版本,其大小,其内容或哈希链。可能会发生混乱。

  • 当线程对put与其他线程使用的某个密钥冲突的密钥执行a操作put,而后一个线程对其密钥进行操作时,则后者可能会看到哈希链引用的陈旧副本。可能会发生混乱。

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

并且,如果你有两个线程同时执行put或remove请求,则有很多竞争条件的机会。

我可以想到三种解决方案:

  1. 使用ConcurrentHashMap
  2. 使用常规HashMap但在外部同步;例如使用原始互斥量,Lock对象等。
  3. HashMap为每个线程使用不同的名称。如果线程确实有一组不相交的键,那么(从算法角度而言)应该不需要它们共享单个Map。确实,如果你的算法包含线程在某个点迭代映射的键,值或条目,则将单个映射拆分为多个映射可以显着加快该部分处理。
2020-03-21