简体   繁体   English

Java ConcurrentHashMap computeIfAbsent() 方法是否支持基于键的“锁定”?

[英]Does Java ConcurrentHashMap computeIfAbsent() method support key-based “locking”?

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent-K-java.util.function.Function- https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent-K-java.util.ZC1C425268E683894F14AB5C741-Absent-K-java.util.ZC1C425268E683894F14AB5C

Assume we have 10 threads calling the following codes with different key value.假设我们有 10 个线程使用不同的键值调用以下代码。 does the "Function" argument provided to the computeIfAbsent method run in parallel, or computeIfAbsent will "lock" the entire table?提供给 computeIfAbsent 方法的“函数”参数是否并行运行,或者 computeIfAbsent 将“锁定”整个表?

Map<String, String> map = new ConcurrentHashMap<>();
map.computeIfAbsent(key, K -> { // long time operation });

There are two ways to interpret the question.有两种方法可以解释这个问题。

The first is, theoretically, does the specification of the ConcurrentHashMap.computeIfAbsent method guarantee to synchronize only on the particular key being computed?第一个是,理论上, ConcurrentHashMap.computeIfAbsent方法的规范是否保证仅在正在计算的特定键上同步? The answer to this comes straight from the documentation for the method :答案直接来自该方法的文档

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.其他线程对 map 的一些尝试更新操作可能会在计算过程中被阻止,因此计算应该简短而简单,并且不得尝试更新此 map 的任何其他映射。

This is ambiguous on whether it synchronizes on the whole map or just the individual key, but it doesn't explicitly promise that updates on other keys can proceed in other threads while value-if-absent is being computed.这对于它是在整个 map 上同步还是仅在单个键上同步是模棱两可的,但它没有明确指出 promise 上的更新可以在其他线程中进行,同时计算 value-if-absent。 It says "some attempted update operations" may be blocked, but doesn't impose a limit on which or how many are blocked.它说“一些尝试的更新操作”可能会被阻止,但不会对被阻止的数量或数量施加限制。 So the strict answer is, no , a conforming implementation is permitted to synchronize on the whole map object, and block all other updates.所以严格的答案是,,允许一致的实现在整个 map object 上同步,并阻止所有其他更新。


The second interpretation of the question is, practically, does the implementation of the method synchronize on just the individual key?问题的第二种解释是,实际上,该方法的实现是否仅在单个键上同步? The answer to this will depend on which implementation, but will come from the source code of that implementation.对此的答案将取决于哪个实现,但将来自该实现的源代码。

From the OpenJDK 8 implementation :OpenJDK 8 实现

Node<K,V> f;
// ...
if(/* ... */) {
    // ...
} /* ... */ else if(/* ... */) {
    Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
        // ...
    }
    // ...
} /* ... */ else {
    // ...
    synchronized (f) {
        // ...
    }
    // ...
}

So the answer (at least if you're using this implementation) is yes , in practice the method synchronizes on an object (either f or r ) representing an individual key/value pair, not the whole map, so updates to other keys should not be blocked while the function is computed.所以答案(至少如果你使用这个实现)是肯定的,实际上该方法在 object (或者f )上r ,代表一个单独的键/值对,而不是整个 Z1D78DC8ED51214E51AEFEZB514 键应该更新到其他在计算 function 时不会被阻塞。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM