为什么睡在线程中会导致“notify”出现问题? Driver.java

为什么睡在线程中会导致“notify”出现问题? Driver.java,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,请和全班同学一起看这一行。我很难找出为什么如果将该行放在主线程的synchronized块中,这个简单的概念验证会失败 谢谢你阅读这篇文章 唤醒正在等待此对象的线程的单个线程 监视器 如果它正在睡觉,那么它就不会等待 还有其他相关问题,当另一个线程处于睡眠状态时,无法到达通知行,因为它保持监视器(锁定),而另一个线程无法在同步块内运行。这通常是这样的,因为等待和通知都必须在相关的同步块内运行(针对同一个监视器)。sleep保持锁定,但wait不保持锁定。因此,当主线程处于睡眠状态时,thr和th

请和全班同学一起看这一行。我很难找出为什么如果将该行放在
主线程的
synchronized
块中,这个简单的概念验证会失败

谢谢你阅读这篇文章

唤醒正在等待此对象的线程的单个线程 监视器

如果它正在睡觉,那么它就不会等待


还有其他相关问题,当另一个线程处于睡眠状态时,无法到达通知行,因为它保持监视器(锁定),而另一个线程无法在同步块内运行。这通常是这样的,因为等待和通知都必须在相关的同步块内运行(针对同一个监视器)。

sleep
保持锁定,但
wait
不保持锁定。因此,当主线程处于睡眠状态时,thr和thr2都无法获得锁,直到主线程通知它们。此时,它们开始等待,无法接收任何
notify()

问题不在于睡眠,而在于主线程几乎总是在一个(有时是两个)创建的线程之前获得锁。如果仅在同步块内打印,则会更清楚地看到正在发生的情况:

synchronized(obj) {
    System.out.println("this thread acquired the lock");
您将看到输出几乎总是线程1,然后是主线程,最后是线程1完成后的线程2(但主线程已经返回)

如果您运行它足够多次,有时两个子线程都会先获取锁,然后锁就完成了


将睡眠移动到主线程中的同步块之外的原因是它允许两个子线程到达各自的等待语句。

问题在于睡眠不会释放监视器,即:当主线程睡眠时,所有其他线程都无法进入同步块,所以他们基本上是和主线程睡在一起


当主线程醒来时,它会发出通知,但由于还没有人进入
wait()
位置,因此没有人在监听。然后主线程等待并释放监视器,因此现在所有线程都可以进入
wait()
状态,但没有人可以唤醒它们。->僵局

我认为这是一种转移注意力的做法。我怀疑问题是其中一个子线程首先进入关键块(在
obj
上同步),因此父线程永远不会到达
obj。通知子线程的
obj。等待(同样,如果父线程确实先进入,信号将在子线程等待它之前出现)。这没有多大意义,对我来说,进入一个关键区域,然后进入睡眠状态20秒。在实时操作系统中,您永远不会这样做,因为如果低优先级任务先进入关键部分,然后决定通过睡眠浪费每个人的时间,那么可能会导致优先级反转。您为什么要使用这样的
静态
互斥锁?你在等待,通知并同步一个obj。是的,我知道。我试图弄明白,当
同步
时,您实际上可以通过调用
等待
来删除
锁定
标志,并允许其他
同步
块继续对
对象
进行处理,然后
通知其他
同步
锁定
标志已被禁用。@user2864740我现在明白你的意思了。这很有道理!你为什么不把它作为答案,至少我可以把它标记为正确答案。
Thread.sleep(2000); // This causes a failure. Move it outside the synchronized and it will work why?
synchronized(obj) {
    System.out.println("this thread acquired the lock");