Java 为什么线程间通信需要notify()
从对象的JAVA文档Java 为什么线程间通信需要notify(),java,multithreading,Java,Multithreading,从对象的JAVA文档notify() 唤醒的线程将无法继续,直到当前 线程放弃此对象上的锁定 这意味着,除非发出通知的线程完成了同步块并释放了锁,否则等待的线程将无法继续。如果是这种情况,那么如果同步块仍要执行,那么让notify()有什么意义呢?如果不唤醒等待的线程并让它完成它的工作,notify()的实际用途是什么?严格来说,我们不会:我们可以让等待的线程运行一个循环,重新获取锁,检查条件,并在短时间内休眠。但是使用wait()和notify()效率更高,因为这样等待的线程就不会一直唤醒并占
notify()
唤醒的线程将无法继续,直到当前
线程放弃此对象上的锁定
这意味着,除非发出通知的线程完成了同步块并释放了锁,否则等待的线程将无法继续。如果是这种情况,那么如果同步块仍要执行,那么让
notify()
有什么意义呢?如果不唤醒等待的线程并让它完成它的工作,notify()
的实际用途是什么?严格来说,我们不会:我们可以让等待的线程运行一个循环,重新获取锁,检查条件,并在短时间内休眠。但是使用wait()
和notify()
效率更高,因为这样等待的线程就不会一直唤醒并占用CPU(并占用锁)。好问题。我会指给你看一下
调用对象.notify
方法的线程启用以前调用对象的线程。现在,线程调度程序将启用wait
。换句话说,等待的线程现在是“runnable
”。虽然它是“可运行的”,但它不是“运行的”
它只能在调用notify
的线程释放锁时继续运行-一种方法是当它退出同步块时
网上有很多关于线程状态的示意图。其中一些完全不正确或令人困惑,因为它们引入了官方文件中没有的术语。这对我来说很有意义。想象一下,如果您需要一个线程等待另一个线程执行它当前可能正在或可能尚未积极处理的任务。例如,一个正在等待作业执行的线程可能需要等待,直到另一个线程将一个作业放在它应该执行的作业列表中(如果该列表为空)。你会怎么做 你不能仅仅使用某种形式的互斥。可能有很长一段时间没有工作要做,并且线程没有在队列上持有任何锁。现在可能没有什么工作要做。执行工作的线程需要等待,而不持有任何锁,直到另一个线程给它一些工作要做 所以在某个地方,有一个线程可以做这样的事情:
为了解决这个问题,我们需要一个原子“解锁并等待”操作。这就是等待所做的。我们还需要一些操作来结束这个等待,它可以被改变共享状态的线程调用,这样我们就不需要再等待了。这就是notify所做的。Notifying就是唤醒正在等待的线程。如果删除了notify,那么等待线程将保持等待状态(除非出现虚假唤醒,但我们暂时不要去那里) (中断会唤醒线程,但指导是仅将其用于取消。中断以特定线程为目标,通知让计划程序决定哪些线程受到影响。) 当线程调用wait时,它必须拥有锁,然后wait方法释放锁 当线程调用notify时,它必须拥有锁 实际上,在通知线程放弃锁之前,通知不能在任何等待的线程上生效。无论如何,通知线程需要做的第一件事就是尝试获取锁。您引用的所有段落都是想说,当线程调用notify时,唤醒不会立即发生 因此,这里发生的情况是,通知线程释放锁并将通知发送给调度程序,调度程序决定通知哪个线程,然后通知线程醒来并争夺锁,以便离开wait方法
notify()
和notifyAll()
用于唤醒在调用notify()
或notifyAll()
的同一对象上调用wait()
的线程。
如果不调用notify()
,那些“等待”的线程将永远等待(尽管JVM规范说线程有时可能会在不调用notify的情况下醒来)。
另外,因为调用notify()
不会释放关联锁
synchronized(lockObject) {
if (size < LIMIT) {
addElement();
lockObject.notifyAll(); //notifying threads that are waiting to get element from empty queue
} else {
lockObject.wait(); // waiting for other thread to get element from queue and make room for new element
}
}
synchronized(lockObject) {
if (size > 0) {
getElement();
lockObject.notifyAll(); // notify threads that there is a room for new element
} else {
lockObject.wait(); // waiting for other thread to put element into the queue
}
}