如果一个人在谷歌上搜索“notify()和notifyAll()之间的区别”,那么会跳出很多解释(撇开javadoc段落)。这都归结于被唤醒的等待线程的数量:notify()中有一个,notifyAll()中有所有线程。
然而(如果我确实理解了这些方法之间的区别),只有一个线程总是被选择用于进一步的监视采集;第一种情况是VM选择的线程,第二种情况是系统线程调度程序选择的线程。程序员不知道它们的确切选择过程(在一般情况下)。
那么notify()和notifyAll()之间有什么有用的区别呢?我遗漏了什么吗?
当你调用wait()的“对象”(期望对象锁)、实习生这将释放锁,物体和帮助的其他线程锁在这个“对象”,在这种情况下,将会有超过1线程等待“资源/对象”(考虑到其他线程也发布了等待上面相同的对象,将会有一个线程的方式填补资源/对象并调用通知/ notifyAll)。
在这里,当您(从进程/代码的同一/另一端)发出同一对象的通知时,这将释放一个阻塞和等待的单个线程(不是所有等待的线程——这个释放的线程将由JVM thread Scheduler挑选,对象上的所有锁获取进程与常规进程相同)。
如果只有一个线程共享/处理这个对象,那么可以在wait-notify实现中单独使用notify()方法。
如果您处于基于业务逻辑的多个线程对资源/对象进行读写的情况,那么您应该使用notifyAll()
现在我正在寻找JVM是如何识别和打破等待线程时,我们发出通知()在一个对象…
我很惊讶居然没有人提到臭名昭著的“失醒”问题(谷歌it)。
基本上:
如果有多个线程在等待同一个条件,
可以让你从状态A转换到状态B的多个线程,
可以让你从状态B转换到状态A的多个线程(通常是与状态1相同的线程),
从状态A转换到状态B应该通知1中的线程。
然后,您应该使用notifyAll,除非您有可证明的保证,丢失的唤醒是不可能的。
一个常见的例子是并发FIFO队列,其中:
多个排队者(1。和3。)可以将队列从空转换为非空
多个退出队列器(2。上面)可以等待条件“队列不是空的”
Empty ->非空应该通知脱队列者
您可以很容易地编写一个交叉操作,其中从一个空队列开始,2个入队者和2个出队者交互,1个入队者保持休眠状态。
这是一个可以与死锁问题相比较的问题。