java - 同步对 ConcurrentMap 中给定键的访问

标签 java guava

我经常想要访问(并且可能添加/删除)给定 ConcurrentMap 的元素,以便一次只有一个线程可以访问任何单个键。做这个的最好方式是什么?同步 key 本身不起作用:其他线程可能通过 equal 实例访问相同的 key 。

如果答案仅适用于 guava 构建的 map 就足够了MapMaker.

最佳答案

在这里查看一个简单的解决方案 Simple Java name based locks?

编辑:该解决方案从解锁到锁定具有明确的先行关系。然而,下一个解决方案(现已撤回)却没有。 ConcurrentMap javadoc 太轻而无法保证这一点。


(Withdrawn) 如果你想重用你的 map 作为锁池,

private final V LOCK = ...; // a fake value
// if a key is mapped to LOCK, that means the key is locked
ConcurrentMap<K,V> map = ...;

V lock(key)
    V value;  
    while( (value=map.putIfAbsent(key, LOCK))==LOCK )
        // another thread locked it before me
        wait();
    // now putIfAbsent() returns a real value, or null
    // and I just sucessfully put LOCK in it
    // I am now the lock owner of this key
    return value; // for caller to work on

// only the lock owner of the key should call this method
unlock(key, value)
    // I put a LOCK on the key to stall others
    // now I just need to swap it back with the real value
    if(value!=null) 
        map.put(key, value);
    else // map doesn't accept null value
        map.remove(key)
    notifyAll();

test()
    V value = lock(key);

    // work on value

    // unlock. 
    // we have a chance to specify a new value here for the next worker
    newValue = ...; // null if we want to remove the key from map
    unlock(key, newValue); // in finally{}

这非常困惑,因为我们出于两个不同的目的重复使用 map 。最好将锁池作为一个单独的数据结构,让 map 简单地作为 k-v 存储。

关于java - 同步对 ConcurrentMap 中给定键的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6758587/

相关文章:

java - Guava - 缓存一张表并在该缓存上使用 get 方法

java - 无法使用 chrome 和 gecko 驱动程序执行 selenium java 程序

Linux 系统调用上的 Java 断点

java - 将 Spring java 配置转换为 xml 配置

java - JPA 乐观锁

java - Guava Splitter.onPattern(..).split() 与 String.split(..) 有何不同?

java - 如何连接两个列表以创建第三个列表?

java - 强制 Maven 命令行参数

java - 如何可靠地从 Guava LoadingCache 中删除记录?

Java 8 循环使用 com.google.common.collect.Iterables.partition 的方法?