Java避免在不相交集的情况下锁定

时间:2013-02-07 09:58:25

标签: java multithreading concurrency java.util.concurrent

我有一个像这样的用例。我的一个方法将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)。

2 个答案:

答案 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锁的尝试都会阻塞,直到所有锁(ReadWrite)都有已被释放。

因此,采用List的方法应该请求Write锁,而其他所有锁请求Read锁定。