1

I thought I would understand the concept of concurrency in Java, but now there is one thing which breaks my understanding:

Why do I have to enclose calls to wait() and notify() methods in synchronized blocks?

Assuming I have two threads: Thread A and Thread B. Also I have an object which I will use as a lock. Now at some point in time, Thread A calls wait() on the object and is blocked afterwards until some other thread calls notify() on the same object. This was my understanding so far and this is fine. But now it sais that I need to enclose those calls in blocks synchronized on this object - indeed, I get an IllegalMonitorStateException if I do not do this. If I add these blocks, it works fine - but why??

I would have expected, that if I use these synchronized blocks, then Thread A will keep the lock on the object forever, because the wait() method keeps on running and Thread B just could not execute notify(), because it could not acquire the lock on the object, as it is still owned by thread A.

However, as I said, in reality it works fine, Thread B can execute notify() which unblocks Thread A ... Can someone please explain me exactly what happens here? How can Thread B acquire the lock?

xingbin
  • 27,410
  • 9
  • 53
  • 103
DanielBK
  • 892
  • 8
  • 23
  • 1
    Read the javadoc. https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--: *The thread releases ownership of this monitor and waits [...]*. – JB Nizet Feb 24 '18 at 13:53

2 Answers2

2

How

When you call wait in the synchronized block, the monitor lock will be released automatically, see the doc:

The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

After the other thread calling notify and exiting its synchronized block, the waiting thread will wake up and try aquire the monitor lock to continue.

Why

Breifly:

A wait() only makes sense when there is also a notify(), so it's always about communication between threads, and that needs synchronization to work correctly.

Check this for more.

xingbin
  • 27,410
  • 9
  • 53
  • 103
  • Ah, thanks, now I get it! So it is just a special behavior of the wait() method that it can release the lock while being still inside the synchronized block - and basically after it starts waiting the lock is free and can be taken by anyone. – DanielBK Feb 24 '18 at 14:03
1

BottomLine: Invocation of wait method actually makes a thread "release its lock" and then suspend.

When wait is invoked, the Thread A releases the lock and suspends execution. At some future time, Thread B will acquire the same lock and invoke Object.notifyAll, informing all threads(including Thread A) waiting on that lock that something important has happened. or Object.notify, informing a random thread(Thread A, if it is the only thread waiting on the object) from threads waiting on that lock that something important has happened.

Some time after the second Thread B has released the lock(when it exists the synchronized block), the first Thread A reacquires the lock and resumes by returning from the invocation of wait.

Alanpatchi
  • 1,177
  • 10
  • 20