我有一个像这样的用例。我的一个方法将List作为参数。当且仅当对象的至少一个已经被某个其他线程锁定时,我需要保护关键部分。如何实现使用java.util.concurrent包?我可以想到基于HashTable的简单解决方案,
之类的东西class ContainsCriticalSections {
HashTable<SomeObject, Thread> map; //shared by multiple threads
someCriticalMethod(List<SomeObject> objects) {
acquireLocks(objects);
//do critical task
releaseLocks(objects);
}
synchronized acquireLock(List<SomeObject> objects) {
bool canLock = false;
while (!canLock) {
for (SomeObject obj : objects) {
if (!map.contains(obj)) {
canLock = true;
}
else if(map.get(obj).equals(Thread.currentThread())) {// ensuring re-entrace
canLock = true;
}
else {
canLock = false;
}
}
if (!canLock) {
wait();
}
}
for (SomeObject obj : objects) {
map.put(obj, Thread.currentThread());
}
}
synchronized releaseLock(List<SomeObject> objects) {
for (SomeObject obj : objects) {
map.reomve(obj);
}
notify();
}
}
因此,在上述情况下,如果两个调用A,B,C和D,E,F不会阻塞。但是,A,B,C和A,E,F将阻止。
但是,我强烈认为这里会有一些既定的范例(使用java.util.Concurrent)。
答案 0 :(得分:1)
你需要获得所有的锁,否则即使你进入临界区时没有人拿着任何锁,有人可能会在你进去的时候获得一把锁。以下是可用于在多个锁下运行任务的方法:
public static void runUnderMultipleLocks (Runnable task, Object ... monitors)
{
runUnderMultipleLocks (task, 0, monitors);
}
private static void runUnderMultipleLocks (Runnable task, int offset, Object ... monitors)
{
if (offset == monitors.length) task.run ();
else
{
synchronized (monitors [offset])
{
runUnderMultipleLocks (task, offset + 1, monitors);
}
}
}
答案 1 :(得分:1)
我怀疑你正在寻找ReadWriteLock
。有关示例,请参阅ReentrantReadWriteLock。
ReadWrite
锁允许多个并发Read
锁,但任何获取Write
锁的尝试都会阻塞,直到所有锁(Read
或Write
)都有已被释放。
因此,采用List
的方法应该请求Write
锁,而其他所有锁请求Read
锁定。