java - 为什么我必须使用相同的对象来同步和调用等待/通知,但使用类 Condition 我可以使用不同的对象?

标签 java conditional-statements locking synchronized

如果当前线程不是对象监视器的所有者,我想从 IllegalMonitorStateException 开始。所以如果我这样做,我会得到异常:

public class Testing {
    Object objLock = new Object();
    void dance(){
        synchronized (this){
            objLock.wait();
        }
    }
}

所以我得出结论,您必须有相同的对象才能同步并调用等待/通知。这是否意味着每个锁只能有一个条件?

但是还有Condition类和Lock接口(interface)。他们是如何设法解决这个问题的?

public class Testing {
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    void dance(){
        lock.lock();
        condition.await();
        lock.unlock();
    }
}

在我发现错误之前,这是否意味着 Lock/Condition 示例允许我们有更多条件?当我刚刚展示 IllegalMonitorStateException 的示例时,为什么会阻止我们这样做。 有人可以解释我的困惑吗? Condition 类是如何“欺骗它”的?或者,如果我说错了什么?

最佳答案

首先,让我们看看official documentation of Conditions :

Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.

并根据official doc of Lock :

Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects.

因此,我将使用这些信息来回答您的问题:

does this mean that Lock/Condition example allows us to have more conditions?

是的,您可以为每个锁使用多个条件,并使用条件组合创建同步逻辑。请参阅官方文档中的示例。

你得到 IllegalMonitorStateException 的原因是你试图在没有监视器的情况下等待对象(你应该传递 objLock 作为同步块(synchronized block)参数)。你没有通过第二个代码示例得到它的原因是你没有在没有监视器的情况下对对象执行非法等待操作。您通过调用 lock.lock() 锁定资源,并在满足某些条件后解锁它们。在此之前,没有其他线程可以访问这些资源。显然,这背后没有任何魔法或诡计。

P.S.:我建议您阅读有关 LockCondition 的文档,因为我发现它们在您遇到问题时非常有用且信息丰富。

关于java - 为什么我必须使用相同的对象来同步和调用等待/通知,但使用类 Condition 我可以使用不同的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63395872/

相关文章:

java - 记录执行的 java 代码的行号

有条件地 hibernate 子标准

java - 如何检查同时满足两个条件

python 锁方法注解

mysql - 对于使用部分组合键的删除,InnoDB 是否会锁定整个表?

c++ - move std::vector 的 std::unique_locks

java - 不输入 Y/N 时返回错误

java - 第二次进入循环时跳过 do...while 循环中的第一行代码 - Java

java - Component.getGraphicsConfiguration 线程安全吗?

javascript - 如何根据变量的值为 url 制定正确的条件? (javascript)