Java避免在不相交集的情况下锁定
我有一个这样的用例。我的一个方法将列表作为参数。当且仅当至少有一个对象已被其他线程锁定时,我需要保护关键部分。如何使用java.util.concurrent包实现?我可以想到简单的基于哈希表的解决方案, 差不多Java避免在不相交集的情况下锁定,java,multithreading,concurrency,java.util.concurrent,Java,Multithreading,Concurrency,Java.util.concurrent,我有一个这样的用例。我的一个方法将列表作为参数。当且仅当至少有一个对象已被其他线程锁定时,我需要保护关键部分。如何使用java.util.concurrent包实现?我可以想到简单的基于哈希表的解决方案, 差不多 class ContainsCriticalSections { HashTable<SomeObject, Thread> map; //shared by multiple threads someCriticalMethod(List<Some
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();
}
}
类包含ScripticalSections{
哈希表映射;//由多个线程共享
someCriticalMethod(列出对象){
获取锁(对象);
//做关键任务
释放锁(对象);
}
同步的acquireLock(列出对象){
bool-canLock=false;
而(!canLock){
对于(SomeObject对象:对象){
如果(!map.contains(obj)){
canLock=true;
}
else if(map.get(obj).equals(Thread.currentThread()){//确保重入
canLock=true;
}
否则{
canLock=false;
}
}
如果(!canLock){
等待();
}
}
对于(SomeObject对象:对象){
put(obj,Thread.currentThread());
}
}
同步释放锁(列出对象){
对于(SomeObject对象:对象){
reomve地图(obj);
}
通知();
}
}
因此,在上述情况下,如果两个调用A、B、C和D、E、F不阻塞。但是,A,B,C和A,E,F会阻塞
但是,我强烈地感觉到这里会有一些既定的范例(使用java.util.Concurrent)。您需要获取所有锁,否则,即使在您进入关键区域时,没有人持有任何锁,当您在里面时,也可能有人获取一个锁。以下是可用于在多个锁下运行任务的方法:
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);
}
}
}
我怀疑您正在寻找
读写锁
。有关示例,请参见
读写
锁允许多个并发的读
锁,但任何试图获得写
锁的尝试都将被阻止,直到所有锁(读
或写
)都被释放
因此,采用
列表
的方法应该请求写入
锁,而其他所有方法都请求读取
锁。@OldCurmudgeon…感谢您提供有关ReadWriteLock的信息。但是,这不符合我的目的。我试图实现的是典型的关键部分保护。@Gopal-你所说的典型是什么意思?对我来说,我对你的代码的解释很像一个ReadWrite
锁。@OldCurmudgeon…很抱歉不清楚。我的意思是,我上面提到的关键部分只包含写操作,并且不是线程安全的。假设我想在缓存中更新(readAndIncrement)对象A、B、C(在单个批中)和D、E、F(在单个批中)。如果thread1尝试更新A、B、C,而thread2尝试更新D、E、F,则不存在任何问题,并且在一个线程中等待另一个线程完成也没有意义。但是,如果thread1尝试更新A、B、C,而thread2尝试更新A、D、E,那么就会出现问题,调用应该序列化。@Gopal-Ah!我懂了。这听起来像是你需要一个单独的读/写锁。也许你可以考虑任何一个S?别忘了在锁定之前对显示器进行分类。“排序”的意思可能是“按正确的顺序排列”,而不是“按升序/降序排列”。比方说,一个线程使用监视器(A、B、C)调用,另一个线程同时使用监视器(C、B、A)调用,即使没有B,也会死锁。