【问题标题】:DeadLock In ConcurrentHashMapConcurrentHashMap中的死锁
【发布时间】:2017-05-09 05:42:58
【问题描述】:

运行时跟随代码,永远不会终止并陷入无限循环。

我不确定卡在哪里。

有趣的是,当我将 AaAa 更改为 AAAA 时,一切都按预期正常工作。

 public class Test {

    public static void main(String[] args) {

        Map<String, Integer> map = new ConcurrentHashMap<>(16);
        map.computeIfAbsent(
                "AaAa",
                key -> {
                    return map.computeIfAbsent(
                            "BBBB",
                            key2 -> 42);
                }
        );
    }

}

谁能帮我理解这种行为。

【问题讨论】:

标签: java concurrenthashmap


【解决方案1】:

"AaAa" 和 "BBBB" 具有相同的 hashCode() - 2031744。 因此,两个键都映射到 Map 的同一个 bin。

外部map.computeIfAbsent 锁定该bin,内部map.computeIfAbsent 尝试在释放锁之前锁定它-因此出现死锁。

【讨论】:

  • @Eran--OMG 你怎么这么快就检查了这一切……太棒了……(Y)
  • @ShowStopper 我碰巧坐在一台打开 Eclipse 的计算机旁边,所以运行 System.out.println ("AaAa".hashCode ()); 和 System.out.println ("BBBB".hashCode ()); 不需要太多时间 :)
  • 我喜欢那些完美的答案很快就会出现。当我不是它的作者时,我只是讨厌它。不过,你得到了我的投票。
  • 一些more 与String.hashCode() 发生冲突。
  • @MehrajMalik 不,它不应该也不能。它们是 2^32 个唯一的哈希码。还有更多独特的字符串。
【解决方案2】:

当两个不同的对象具有相同的哈希码时,我们称之为collision。

碰撞并不重要,它只是意味着单个存储桶中有多个对象,因此HashMap 查找必须再次查找才能找到正确的对象。大量的冲突会降低系统的性能,但不会导致错误的结果。

但是,如果您将哈希码误认为是对象的唯一句柄,例如将其用作 Map 中的键,那么您有时会得到错误的对象。

在Java 中有4,294,967,296 隔间(2^32 可能的int 值)。拥有 40 亿个插槽,碰撞似乎极不可能,对吧? 因为即使碰撞很少见,它们也是不可避免的。例如,字符串"Aa" 和"BB" 产生相同的hashCode: 2112。"AaAa" 和"BBBB" 具有相同的hashCode() - 2031744 等等。

相同的对象在运行的进程中必须具有相同的哈希码

请注意,这并不意味着以下常见的误解:

  • 不相等的对象必须有不同的哈希码 - 错误!
  • 具有相同哈希码的对象必须相等 - 错误!

【讨论】:

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