为什么我们必须使用"while"来检查竞争条件而不是"如果"

scu*_*gxl 6 java multithreading while-loop wait

我在"Thinking in java"中阅读了以下代码.

synchronized(obj)
    {
        while (condition_not_matched)
        {
            obj.wait();
        }
        //continue
        dosomething();

    }
Run Code Online (Sandbox Code Playgroud)

我的想法:
使用"if"是可以的,因为"等待"意味着它必须得到obj的锁定监视器,并且这里只能执行一个线程.

(1)为什么这里使用"while(condition)"而不是"if"?
(2)执行"obj.wait()"时发生了什么?currrent线程是否释放了"obj"的锁定?
(3)当另一个线程执行"obj.notify()"时,前一个线程发生了什么(它是否重新获取了obj的锁定?如果是,它必须是condition_not_matched,所以"如果"就足够了.)
我是错误?

Nat*_*hes 5

使用if检查而不是在循环中反复检查是一个错误。使用循环有多种原因。

一种是“虚假唤醒”,这意味着wait方法可以在没有通知线程的情况下返回:基于退出wait方法的线程,推断必须已被通知是无效的。这可能不会发生很多,但是有可能需要处理。

但是主要原因是这一点:当线程等待时,它释放锁。当它收到通知时,它没有锁,必须再次获取它才能退出wait方法。仅仅因为线程被通知并不意味着它是下一个获得锁的线程。如果线程根据线程没有锁所有权时发生的事情来决定要做什么,那么在通知发生到线程发生之间,多个线程可能有机会对同一个共享对象执行操作。得到了锁,共享对象的状态可能不是线程认为的那样。使用while循环可以使线程在保持锁定的情况下检查它再次等待的条件,并在继续进行之前确认条件仍然有效。


小智 1

语句通过运行一次来if​​检查表达式是真还是假,然后仅在表达式为真时才运行语句内的代码。

然而

条件继续执行while 语句中的代码,直到表达式为 true while。此外,当您不知道可能需要循环条件多少次时,更适合使用 while 循环。

obj.wait()- 导致当前线程等待,直到另一个线程调用该notify()方法或nofityAll()在这种情况下调用相应对象的方法。如果超时作为参数传递,则执行将等待,直到经过一定的时间。

obj.notify()将唤醒正在相应对象监视器上等待的单个线程。仅当当前线程放弃对象上的锁后,唤醒的线程才会继续执行。