0

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

4

2 回答 2

1

我怀疑你正在寻找一个ReadWriteLock. 有关示例,请参见ReentrantReadWriteLock 。

一个ReadWrite锁允许多个并发Read锁,但任何获取锁的尝试Write都会阻塞,直到所有锁(ReadWrite)都被释放。

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

于 2013-02-07T10:34:27.733 回答
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);
        }
    }
}
于 2013-02-07T10:09:11.947 回答