Why Lock condition await must hold the lock

后端 未结 6 1197
梦毁少年i
梦毁少年i 2020-12-29 05:29

I am in doubt with that , in Java language, we need to acquire the lock, before we await some condition to be satisfied.

For example, int java monitor lock:

6条回答
  •  孤独总比滥情好
    2020-12-29 06:25

    Well, what are we waiting for? We are waiting for a condition to become true. Another thread will make the condition true, then notify the waiting threads.

    Before entering wait, we must check that the condition is false; this check and the wait must be atomic, i.e. under the same lock. Otherwise, if we enter the wait while the condition is already true, we'll likely never wakeup.

    Therefore it is necessary that the lock is already acquired before calling wait()

    synchronized(lock)
    {
        if(!condition)
            lock.wait();
    

    If wait() automatically and silently acquires lock, a lot of bugs will go undetected.


    Upon wakeup from wait(), we must check the condition again -- there's no guarantee that the condition must become true here (for lots of reasons - spurious wakeup; timeout, interruption, multiple waiters, multiple conditions)

    synchronized(lock)
    {
        if(!condition)
            lock.wait();
        if(!condition)   // check again
            ...
    

    Typically, if the condition is still false, we'll wait again. Therefore the typical pattern is

        while(!condition)
            lock.wait();
    

    But there are also cases where we don't want to wait again.


    Could there ever be legit use cases where naked wait/notify make sense?

    synchronized(lock){ lock.wait(); }
    

    Sure; an application can be made up with naked wait/notify, with well defined behavior; argument can be made that this is the desired behavior; and this is the best implementation for that behavior.

    However, that is not the typical usage pattern, and there is no reason to account for it in API design.

提交回复
热议问题