我遇到以下情况:我正在同时处理具有给定键的请求。我可以同时处理任意数量的请求,只要进行中的每个键都是唯一的。
我是 Java 并发方面的新手。一定有一些模式/实用程序/现有问题,但我不知道要搜索什么。希望有人能为我指明正确的方向,或对我目前所做的发表评论。
这个类管理锁:
class LockMap<K> {
private Map<K, Object> locks = new HashMap<>();
void acquireLock(K key) throws InterruptedException {
Object lockObj;
synchronized (locks) {
lockObj = locks.get(key);
if (lockObj == null) lockObj = new Object();
locks.put(key, lockObj);
}
synchronized (lockObj) {
lockObj.wait();
}
}
void releaseLock(K key) {
Object lockObj;
synchronized (locks) {
lockObj = locks.get(key);
locks.remove(key);
}
if (lockObj != null) {
synchronized (lockObj) {
lockObj.notify();
}
}
}
}
然后我像这样使用锁管理器:
// lockMap is instance of LockMap shared across all threads
void doSomething(K key) {
lockMap.acquireLock(key);
try {
// something
} finally {
lockMap.releaseLock(key);
}
}
这是正确的做法吗?
最佳答案
这个怎么样:
创建一个 ConcurrentHashMap<K,Semaphore>
ConcurrentMap<K, Semaphore> myMap = new ConcurrentHashMap<>();
在你的doSomething()
方法,使用 putIfAbsent()
方法 to 将具有一个许可的信号量添加到 map ,仅当键不存在于 map 中时。
随后执行 get()
在键上获取该键的信号量,然后做你的事情。完成后释放信号量。
void doSomething(K key) {
myMap.putIfAbsent(key, new Semaphore(1));
Semaphore s = myMap.get(myKey);
s.aquire();
try {
// do stuff
} finally {
s.release();
}
}
这个方案唯一真正的问题是如果你的键列表会无限增长,我没有一个很好的无竞争条件的策略来从 map 中删除信号量。 (但如果你知道你会一遍又一遍地重复使用相同的键,或者列表会增长缓慢,那么也许这没问题。)
关于java - 管理多个锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21286831/