如何在不是线程的对象上调用 wait() 和 notify() 方法?

2022-08-31 20:54:46

如何在不是线程的对象上调用 和 方法?这真的没有意义,不是吗?wait()notify()

当然,它必须有意义,但是,因为这两种方法可用于所有 Java 对象。有人可以提供解释吗?我无法理解如何使用 和 在线程之间进行通信。wait()notify()


答案 1

锁定是关于保护共享数据。

锁位于受保护的数据结构上。线程是访问数据结构的事物。锁位于数据结构对象上,以防止线程以不安全的方式访问数据结构。

任何对象都可以用作固有锁(表示与 结合使用)。这样,您可以通过将同步修饰符添加到访问共享数据的方法来保护对任何对象的访问。synchronized

和 方法在用作锁的对象上调用。锁是一个共享通信点:waitnotify

  • 当具有锁的线程调用它时,等待同一锁的其他线程会收到通知。当具有锁的线程调用它时,等待同一锁的其中一个线程会收到通知。notifyAllnotify

  • 当具有锁的线程调用它时,该线程释放锁并进入休眠状态,直到a)它收到通知,或者b)它只是任意唤醒(“虚假唤醒”);由于这两个原因之一,等待线程仍然卡在调用中,直到它唤醒,然后线程必须重新获取锁,然后才能退出等待方法。wait

请参阅有关受保护块的 Oracle 教程,Drop 类是共享数据结构,使用生产者和使用者可运行的线程正在访问它。锁定 Drop 对象控制线程访问 Drop 对象的数据的方式。

线程在 JVM 实现中用作锁,建议应用程序开发人员避免使用线程作为锁。例如,Thread.join的文档说:

此实现使用 this.wait 调用的循环,条件是 this.isAlive。当线程终止 this.notifyAll 方法时,将调用该方法。建议应用程序不要在线程实例上使用等待、通知或通知全部。

Java 5 引入了显式锁实现 。这些比隐式锁更灵活;有类似于等待和通知(等待和信号)的方法,但它们在条件上,而不是在锁上。具有多个条件使得仅针对那些等待特定类型通知的线程成为可能。java.util.concurrent.locks.Lock


答案 2

您可以使用 和 来同步逻辑。作为示例wait()notify()

synchronized (lock) {
    lock.wait(); // Will block until lock.notify() is called on another thread.
}

// Somewhere else...
...
synchronized (lock) {
    lock.notify(); // Will wake up lock.wait()
}

成为班级成员lockObject lock = new Object();