0

我在资源池的上下文中使用 ReentrantLock 中的条件,据我所见,它简化了线程通信。我的问题是,我最终会有机地编写奇怪的条件语句,例如 acquireMapEmpty、freeQueueNotEmpty、更改等待和单个不同的东西。从技术上讲,它们可以全部被一个条件句替换或分解为更多条件句——是否有经验法则:

  1. 识别条件
  2. 弄清楚你是否有太多或太少
  3. 当你在正确的轨道上或偏离路线时

这是删除资源的示例。

 public boolean remove(R resource) throws InterruptedException {

    System.out.println("Remove, resource: " + resource + " with thread: " + Thread.currentThread().getName());
    if (resource == null) {
        throw new NullPointerException();
    }
    mainLock.lock();
    try {
        if (!isOpen) {
            throw new IllegalStateException("Not open");
        }
        Object lock = locks.get(resource);
        if (lock == null) {
            return false;
        }
        if (freeQueue.remove(resource)) {
            locks.remove(resource);
            if (!freeQueue.isEmpty()) {
                freeQueueNotEmpty.signalAll();
            }
            return true;
        }
        while (!freeQueue.contains(resource)) {
            change.await();
            if (!isOpen) {
                throw new IllegalStateException("Not open");
            }
            lock = locks.get(resource);
            if (lock == null) {
                return false;
            }
        }
        if (freeQueue.remove(resource)) {
            locks.remove(resource);
            if (!freeQueue.isEmpty()) {
                freeQueueNotEmpty.signalAll();
            }
            return true;
        }
        return false;
    } finally {
        mainLock.unlock();
    }
}
4

2 回答 2

1

在我看来,这里没有经验法则。
这真的取决于用例,同步根本不是一个简单的话题。当然,你不应该用锁“耗尽”你的系统——锁是一种昂贵的资源。
如果您觉得需要协调线程并保护共享资源,那么您别无选择,只能使用同步对象。
每次使用同步对象,例如锁或从锁获得的条件时,您应该问自己用例是什么,您真的需要锁,需要协调哪些其他线程(它们是什么?流)。
我想把这个问题稍微跑题,给你一个例子——我发现我们有几个线程使用同步关键字,
但是有些执行读取,有些执行写入,所以我切换到 ReaderWriterLock -
所以应该是你的情况,
不要使用各种同步对象,只是因为它们很酷 - 仔细了解它们是否以及在哪里真正需要。

于 2012-11-20T06:28:56.083 回答
1

好吧,根据经验,我倾向于拥有与线程阻塞的原因一样多的条件变量。基本原理是,当您发出一个条件变量信号时,您想唤醒一个线程,该线程正在等待您发出信号的状态的特定变化,并且您真的,真的想避免“雷鸣群”综合症 -唤醒所有线程,在某个条件下被阻塞,只是让其中一个取得进展,而所有其他线程都重新进入睡眠状态,同时浪费了宝贵的 CPU 时间并破坏了缓存。

于 2012-11-20T23:28:18.250 回答