运行后的代码,永远不会终止并陷入无限循环。
我不知道它会被困在哪里。
有趣的是,当我将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);
}
);
}
}
有人可以帮助我理解这种行为。
答案 0 :(得分:10)
"AaAa"
和"BBBB"
具有相同的hashCode()
- 2031744。
因此,两个键都映射到Map的同一个bin。
外部map.computeIfAbsent
锁定bin,内部map.computeIfAbsent
在释放锁之前尝试锁定它 - 因此死锁。
答案 1 :(得分:0)
每当两个不同的对象具有相同的哈希码时,我们将其称为collision
。
碰撞并不重要,它只是意味着一个存储桶中有多个对象,因此HashMap
查找必须再次查找才能找到正确的对象。很多冲突会降低系统的性能,但不会导致不正确的结果。
但是,如果您将哈希码误认为对象的唯一句柄,例如将其用作Map
中的键,那么您有时会得到错误的对象。
在Java
中,有4,294,967,296
个分区(2^32
个int
个"Aa"
个值。有40亿个插槽,碰撞似乎极不可能,对吧? 因为即使碰撞很少见,也是不可避免的。例如,字符串"BB"
和hashCode: 2112
生成相同的"AaAa"
。"BBBB"
和hashCode() - 2031744
具有相同的RewriteRule
等等。
相同的对象在正在运行的进程中必须具有相同的哈希码
请注意,这并不意味着以下常见误解: