【问题标题】:Concurrent HashMap thread safety and happens-before relationship并发HashMap线程安全和happens-before关系
【发布时间】:2020-01-05 16:08:30
【问题描述】:

ConcurrentHashMap 采购javadoc,我阅读了以下关于所述集合的线程安全性的声明。

发件人:Class ConcurrentHashMap

检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括putremove)。检索反映了最近完成的更新操作在其开始时保持的结果。对于 putAllclear 等聚合操作,并发检索可能仅反映插入或删除某些条目。

我觉得这一段自相矛盾。准确地说,语句 2 表示检索反映了最近完成的操作,而语句 3 几乎说聚合函数不能保证这种行为。

这是否意味着像 putAllclear 这样的聚合操作仍然是一个冒险的赌注?

【问题讨论】:

  • ConcurrentHashMap 是(大部分)非阻塞集合类型之一。在更新其内容时,它通过保持几个不同的锁来锁定地图的一部分。这并不能保证特定方法后的同步。它保证您不会覆盖数据或损坏您的收藏。如果您需要一个始终为您提供其数据的最新视图的集合,请切换到 Collections.synchronizedMap,它将每个操作锁定在同步块中。这还有其他含义,例如当大量线程更新或查询地图时的锁争用

标签: java synchronized java.util.concurrent concurrenthashmap


【解决方案1】:

这是否意味着像 putAll 和 clear 这样的聚合操作仍然是一个冒险的赌注?

他们对“检索操作......不阻塞”的承诺对他们可以承诺的其他内容施加了一些重大限制。例如,map.get(k) 调用必须立即返回 null 或一些 v,之前的 put(k,v) 具有相同的 kget(k) 调用不能等待其他线程完成map.putAll(someEnormousOtherMap) 调用。他们承诺不会阻塞!

基本上,他们无法兑现承诺,除非唯一看似原子的操作是单个键/值对的插入/删除/替换。在不破坏 non-blocking-get() 承诺的情况下实现聚合操作的唯一方法是将它们实现为对一次操作一个键/值对的原子原语的非原子调用序列。

【讨论】:

    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    相关资源
    最近更新 更多