ConcurrentHashMap中的死锁

时间:2017-05-09 05:42:58

标签: java concurrenthashmap

运行后的代码,永远不会终止并陷入无限循环。

我不知道它会被困在哪里。

有趣的是,当我将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);
                }
        );
    }

}

有人可以帮助我理解这种行为。

2 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分:0)

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

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

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

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

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

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

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