3
public class ShareResource {

private int n = 0;

public synchronized void p() throws InterruptedException {
    while (n > 0) {
    wait();
    }
    n++;
}

public synchronized void r() {
  n = 0;
  notifyAll();
}

}

If I started two threads with this resource and they are both at wait() and I called the method r() in the resource would this wake both threads without checking the condition? Would the code be read until the end of the method in both threads?At the "same" time?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
Ventura
  • 97
  • 12
  • Both threads would wake up, but since code is `synchronized`, only one thread at a time can run, so one of the threads would execute `n++` before the other threads executes `while (n > 0)`. – Andreas Jan 08 '19 at 00:18

2 Answers2

1

Would the code be read until the end of the method in both threads? At the "same" time?

No and no. How notifyAll() works is that every object eventually gets to execute their code after waking up from the wait(). However, only one thread executes at a time. Because of this, after one thread exits the loop via calling r(), it increments the counter and therefore doesn't let out the other thread. Therefore, only one of the Threads would execute to the end - not in both threads.

If I started two threads with this resource and they are both at wait() and I called the method r() in the resource would this wake both threads without checking the condition?

I assume you mean that the while loop is exited when you mean "without checking the condition." As seen above, this is not the case for both threads.

TL;DR: notifyAll() only lets one Thread execute at a time, but all of them eventually will eventually execute.

Source: https://stackoverflow.com/a/37046/10869762

Leftist Tachyon
  • 304
  • 1
  • 15
1

Both waiting threads receive a notification. Both waiting threads wake up inside the loop. Both have to check the condition in order to get out of the loop. But one of the waiting threads will go first, and will slam the door shut on the other one.

When a waiting thread gets notified it is still in the wait method, it can't leave the wait method until it acquires the lock. (Remember the wait is inside a synchronized method and the thread gave up the lock on the ShareResource object when it started waiting.) Of course only one thread can acquire the lock at a time.

Of the two notified threads, the first to acquire the lock will leave the wait method, then check the loop condition. It finds that n is 0 and it can exit the loop. Then the thread increments n. All of this happens with the lock held so no other threads can interfere.

All this time the second thread has been blocked; it was woken up by the same notification as the first thread, but it couldn't get the lock. Once the first thread has exited the p method, releasing the lock, the second thread can take the lock and exit the wait method. At that point it checks the while loop condition, finds n is greater than 0 thanks to the first thread, then enters the wait method again and it's back where it started.

Notice that notifyAll is typically wasteful because multiple threads get woken up but only one can make progress.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276