您可能会为每个条目保留一个锁。这将允许并发的非锁定更新,除非两个线程尝试访问同一个元素。
class LockedReference<T> {
Lock lock = new ReentrantLock();;
T value;
LockedReference(T value) {this.value=value;}
}
LockedReference<T> ref = new LockedReference(value);
ref.lock.lock(); //lock on the new reference, there is no contention here
try {
if (map.putIfAbsent(key, ref)==null) {
//we have locked on the key before inserting the element
doSomethingElse();
}
} finally {ref.lock.unlock();}
之后
Object value;
while (true) {
LockedReference<T> ref = map.get(key)
if (ref!=null) {
ref.lock.lock();
//there is no contention, unless a thread is already working on this entry
try {
if (map.containsKey(key)) {
value=ref.value;
break;
} else {
/*key was removed between get and lock*/
}
} finally {ref.lock.unlock();}
} else value=null;
}
一种更好的方法是重写ConcurrentHashMap
并有一个putIfAbsent
接受 a的版本Runnable
(如果放置了元素则执行)。但这会复杂得多。
基本上,ConcurrentHashMap
实现锁定段,它位于每个条目一个锁和整个地图的一个全局锁之间。