ConcurrentHashMap 中的活锁

Live Lock in ConcurrentHashMap

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

概念上的调用调用如下所示

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

(在计算之间燃烧了大约 3 毫秒的 cpu)。不幸的是,我无法想出好的单元测试来始终如一地重现问题。

不过

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

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

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

非常感谢任何帮助!

好吧,ConcurrentHashMap.computeIfAbsent 文档明确指出:

Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.

强调我的。在内部 computeIfAbsent 同步包含您的密钥的 hash-table 条目。当您修改另一个恰好与当前正在处理的条目相同的密钥时,您可能会遇到意外锁定。

一般来说你应该避免这样的修改。不幸的是,您没有为您的问题提供足够的上下文,所以我无法提出替代解决方案。