Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must wait and notify be called from synchronized block/method? [duplicate]

In the book I'm reading it says:

This technique is needed due to a race condition that would otherwise exist between setting and sending the notification and testing and getting the notification. If the wait() and notify() mechanism were not invoked while holding the synchronization lock, there would be no way to guarantee that the notification would be received.

Don't understand what this exactly means, why can the race condition happen?

EDIT: Hmmmm, I see now that this is possibly a duplicate question of Why must wait() always be in synchronized block , but it seams that the answers focus on making the condition check and going to wait synchronized.

Counterexample from shrini1000:

I can still do something like:
while(!condition) { synchronized(this) { wait(); } }
which means there's still a race between checking the condition and waiting even if wait() is correctly called in a synchronized block. So is there any other reason behind this restriction, perhaps due to the way it's implemented in Java?

like image 813
croraf Avatar asked Feb 01 '26 01:02

croraf


1 Answers

It must be all about the technique author must have presented before the article you have copied in question. I am not sure which book you are reading but I will try to answer this question.

I read a similar book "Thinking in Java" that talked about the same race condition. It suggests that this can be prevented using wait and notify so that the code doesn't miss the notify signal.

When two threads are coordinated using notify( )/wait( ) or notifyAll( )/wait( ), it’s possible to miss a signal. Suppose T1 is a thread that notifies T2, and that the two threads are implemented using the following (flawed) approach:

T1:

synchronized(sharedMonitor) {
    <setup condition for T2>
    sharedMonitor.notify();
}

T2:

while(someCondition) {
    // Assume that T2 evaluates someCondition and finds 
    // it true, now when program goes to next line thread
    // scheduler switches to T1 and executes notify again
    // after when control comes to T2 it blindly executes
    // wait(), but it has already missed notify so it will
    // always be waiting.

    .... some code ....

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

The (setup condition for T2) is an action to prevent T2 from calling wait( ), if it hasn’t already.

The solution is to prevent the race condition over the someCondition variable. Here is the correct approach for T2:

synchronized(sharedMonitor) {
    while(someCondition) {
        sharedMonitor.wait();
    }
}

like image 146
Vipin Avatar answered Feb 03 '26 15:02

Vipin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!