3

当用于计算的函数在同一个映射上调用 #computeIfAbsent 时,我在并发哈希映射 #computeIfAbsent 中达到了实时锁定条件。

概念上调用调用如下所示

final Map<String, Boolean> map = new ConcurrentHashMap<>();
map.computeIfAbsent("k1", k1 -> map.computeIfAbsent("k2", k2 -> Boolean.TRUE));

(计算之间消耗了大约 3ms 的 cpu)。不幸的是,我无法提出好的单元测试来一致地重现问题。

然而

如果计算函数试图删除调用它的键,还有另一个活锁可能会提供一些线索:

 final Map<String, Boolean> map = new ConcurrentHashMap<>();
 map.computeIfAbsent("k", k -> map.remove("k"));

虽然第二个示例是并发哈希映射的使用相当复杂,但它会产生与第一个活锁相同的堆栈跟踪,因此可能会有所帮助。

任何帮助将不胜感激!

4

1 回答 1

4

那么ConcurrentHashMap.computeIfAbsent文档明确地说:

在计算过程中,其他线程对该映射的某些尝试更新操作可能会被阻塞,因此计算应该简短而简单,并且不得尝试更新该映射的任何其他映射。

强调我的。computeIfAbsent在包含您的密钥的哈希表条目上进行内部同步。当您修改另一个恰好落入与当前正在处理的条目相同的条目时,您可能会遇到意外锁定。

一般来说,您应该避免此类修改。不幸的是,您没有为您的问题提供足够的背景信息,因此我无法提出替代解决方案。

于 2015-09-20T11:18:08.420 回答