为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

婷婷同学_ 2019-10-26 13:05:55
如果我有两个多个线程访问一个HashMap,但确保它们永远不会同时访问同一密钥,那是否仍会导致争用情况?
查看完整描述

3 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

在@dotsid的回答中,他说:

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

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

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

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

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

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

而且,如果您有两个线程同时执行putremove请求操作,则有很多竞争条件的机会。

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

  1. 使用ConcurrentHashMap

  2. 使用常规HashMap但在外部同步;例如使用原始互斥量,Lock对象等。

  3. HashMap为每个线程使用不同的名称。如果线程确实有一组不相交的键,那么(从算法的角度来看)应该不需要它们共享一个Map。确实,如果您的算法涉及线程在某个点迭代映射的键,值或条目,则将单个映射拆分为多个映射可以显着加快该部分处理。


查看完整回答
反对 回复 2019-10-26
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

只需使用ConcurrentHashMap。ConcurrentHashMap使用覆盖多个哈希桶的多个锁,以减少争用锁的机会。获取无争议的锁会对性能产生边际影响。


回答您的原始问题:根据javadoc,只要地图的结构不变,就可以了。这意味着根本不会删除任何元素,也不会添加地图中尚未存在的新键。替换与现有键关联的值就可以了。


如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改该映射,则必须在外部进行同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已经包含的键相关联的值不是结构修改。)


尽管它不能保证可见性。因此,您必须偶尔愿意接受检索过时的关联。


查看完整回答
反对 回复 2019-10-26
?
噜噜哒

TA贡献1784条经验 获得超7个赞

这取决于您在“访问”下的含义。如果您只是阅读,甚至可以读取相同的键,只要在“ 事前发生 ”规则下保证的数据可见性即可。这意味着HashMap不应更改,所有更改(初始构造)都应在任何读者开始访问之前完成HashMap。


如果您HashMap以任何方式进行更改,那么您的代码就会被破坏。@Stephen C提供了很好的解释。


编辑:如果第一种情况是您的实际情况,我建议您使用Collections.unmodifiableMap()以确保您的HashMap永不更改。指向的对象HashMap也不应更改,因此积极使用final关键字可以为您提供帮助。


正如@Lars Andren所说,ConcurrentHashMap在大多数情况下是最佳选择。


查看完整回答
反对 回复 2019-10-26
  • 3 回答
  • 0 关注
  • 404 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信