【问题标题】:ConcurrentHashMap lockingConcurrentHashMap 锁定
【发布时间】:2012-05-14 18:37:26
【问题描述】:

我在某处读到ConcurrentHashMap,整个地图对象没有被锁定,而是在地图的一部分上进行了锁定。

有人能详细说明什么时候出现锁定吗?

读取 Map 时不涉及锁定但更新时只使用锁定是对的吗?

【问题讨论】:

标签: java concurrenthashmap


【解决方案1】:

是的,ConcurrentHashMap 使用了多个锁(默认情况下,16 个),每个锁控制一个哈希段。

在特定段中设置数据时,会获得该段的锁定。

获取数据时,使用易失性读取。如果 volatile 读取导致未命中,则在最后一次尝试成功读取时获取该段的锁定。

【讨论】:

  • 我没有得到“如果 volatile 读取导致未命中,则在最后一次尝试成功读取时获得该段的锁定”。能不能详细解释一下?
  • @anand 根据 JMM,在对象完成构造后,构造函数中字段的可变写入可能对线程可见,并且对其他线程可见(对于最终字段,这是不正确的) )。他所指的锁将确保发生在对其他读取的易失性写入的排序之前发生。注意:这可能会发生,但可能永远不会发生,而且我在 Java 6 中读过的内容永远不会发生 - 由于所有的混乱,有人谈论将其删除。
  • 并且只是为了明确构造函数完成是指桶的条目。
【解决方案2】:

在保持线程安全的同时尽可能减少锁定。

为了解释“部分 Map 被锁定”,这意味着在更新时,只有 Map 的“1/concurrencyLevel”(基于 key 的哈希)被锁定。这意味着如果两个更新都影响单独的“桶”,它们仍然可以安全地同时执行,从而最大限度地减少锁争用,从而最大限度地提高性能。

更重要的是,相信 JDK 实现 - 您不必担心 JDK 中的实现细节(一方面,它可能会随着版本的不同而变化)。相反,只需专注于编写您的代码。

【讨论】:

    【解决方案3】:

    ConcurrentHashMap 使用可重入锁机制。 ConcurrentHashMap 使用段而不是存储桶,当新记录获取插入锁时,将仅在段而不是完整的段列表上获取。所以这里的想法清楚地表明多级锁将在同一时间获得。

    由于没有明确设置并发级别,因此 ConcurrentHashMap 被分为 16 个段。并且每个段都充当一个独立的 HashMap。

    ConcurrentHashMap 的读操作没有加锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-18
      • 1970-01-01
      • 2015-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      相关资源
      最近更新 更多