我经常想要访问(并且可能添加/删除)给定的元素ConcurrentMap,以便一次只有一个线程可以访问任何单个键。做这个的最好方式是什么?同步密钥本身不起作用:其他线程可能通过equal实例访问同一密钥。
如果答案仅适用于guava MapMaker构建的地图就足够了。
在这里查看一个简单的解决方案基于简单 Java 名称的锁?
编辑:该解决方案具有从解锁到锁定的明确发生之前关系。然而,现在已撤回的下一个解决方案却没有。javadocConcurrentMap太轻,无法保证这一点。
(已撤回) 如果你想将你的地图重新用作锁池,
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{}
Run Code Online (Sandbox Code Playgroud)
这非常混乱,因为我们为了两个不同的目的而重复使用地图。最好将锁池作为一个单独的数据结构,而将map简单地作为kv存储。
| 归档时间: |
|
| 查看次数: |
5187 次 |
| 最近记录: |