Why do we need to synchronize on one object for notification () to work

I was getting java.lang.IllegalMonitorStateException . I called this question and it solved my problem. First answer

 To be able to call notify() you need to synchronize on the same object. synchronized (someObject) { someObject.wait(); } /* different thread / object */ synchronized (someObject) { someObject.notify(); } 

My question is: why do we need to synchronize the same declaration of the object, how does it work?

As I understand it, when we talk

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

we get a lock on someObject and then call wait (). Now, how can another thread get a lock on the same object to call notify () on it? What am I missing?

+6
source share
4 answers

Why do notify block?

Imagine this scenario:

 synchronized(x){ while(x.count < 4) { x.wait(); //... } } 

Imagine now notify in another place without blocking around it:

 //... println(x.count); // print 3 x.count++; if(count == 4) x.notify() //... 

At first glance, everything always sounds like you would expect.
However, imagine a race condition:

 //Thread1 enters here synchronized(x){ while(x.count < 4) { //condition is judged true and thread1 is about to wait //..but..ohh!! Thread2 is prioritized just now ! //Thread2, acting on notify block side, notices that with its current count incrementation, //count increases to 4 and therefore a notify is sent.... //but...but x is expected to wait now !!! for nothing maybe indefinitely ! x.wait(); //maybe block here indefinitely waiting for a notify that already occurred! } } 

If we had a way to report this side to notify :

Topic 1: "Humm .. notify , you are pretty, but I just started evaluating my condition ( x.count < 4 ) for true, so please ... don’t be stupid just sending the expected notification (before I let you down my status is pending), otherwise it would be ridiculous for me to wait for things that have already passed "

Thread2: "Alright, alright ... I would put a lock around my logic to stay consistent, to send my notification after , your waiting call will release our shared lock, and thus you will get this notification allowing you to exit your waiting state;) "

Thus, always place the lock on the notify side on the same object that is held on hold in order to avoid this situation and so that the relationship is always consistent.

=> The logic leading to notify and the logic leading to wait should never overlap.

+7
source

According to javadoc for Object # wait ()

The current thread must have this object monitor . Issues threads ownership of this monitor and waits until another thread tells the threads waiting on this object monitor to wake up either through the call notification method or the notifyAll method. Then the thread waits until it can again obtain ownership of the monitor and resume execution.

To use wait / notify, the thread must have a lock, otherwise IllegalMonitorStateException is thrown

Throws: IllegalMonitorStateException - if the current thread is not the owner of the object’s monitor.

Why

So wait() makes the current thread release the lock

notify() signals another waiting thread (s), which then tries to obtain a lock.

To execute the current thread must have a lock. And that makes sense!

Edit

  • Why, to call the wait () call, locking the lock is now pretty obvious.

  • But why is it necessary for the thread to call notify () while holding the lock? Well, in order to prove its authenticity . Otherwise, any thread may continue to fire false notifications , and waiting threads will be interrupted. Fortunately, this is not so.

+5
source

wait / notify is typically used to wait for some other thread to complete to complete a task, or to wait for a certain condition to complete.

Suppose we have an object called objectA and two threads called thread1 and thread2.
thread1 has some thread safety issue, so it gets an objectA monitor using a synchronized block.

  synchronized (objectA) { //here thread1 owns objectA monitor } 

In a java call, wait () means freeing up monitors so that other threads can receive this monitor and perform their tasks, and the current thread goes into a state called an object waiting for the monitor.

  synchronized(objectA){ //here thread1 owns objectA monitor. objectA.wait(); //here thred1 releases monitor of objectA monitor and goes into waiting state and waits to get objectA monitor once again to complete its task. } 

Now thread2 can own the monitor objectA and does its job.

  synchronized(objectA){ //here thread2 owns objectA monitor. //some task; } 

After completing the task, it notifies other threads of the wait state that it issues a monitor to its object. note that to call notify (), the stream must also be the owner of the object’s monitor .

  synchronized(objectA){ //here thread2 owns objectA monitor. //some task; objectA.notify(); //it signals some other thread that it can wake up from wait,so that other waiting threads can owns objectA monitor } 

here calling wait () on objectA and calling notify () on another object (say objectB) does not make sense for thread1.Since thread1 waits to get a monitor on objectA and not on another object (say objectB).

Update Why obtain monitor to call notify()
to call notify (), we need to get a monitor, because it is guaranteed that two threads trying to call notify () on the same object will not step on each of the fingers (in the aviod race state).
why do we need to block before notification

+1
source

Looking through the source code of the JVM Hotspot, I found this: The notify() method notify() object's monitor set of expectations. (The set of object expectations is the set of threads that wait() typed on it.) If access to the waiting set has not been synchronized, it can happen: for example, a stream can be deleted from the set, woken up. Requiring the calling thread to own the monitor before calling notify() solves this problem, although other solutions may exist.

There are other arguments, such as a notification that is triggered without holding a monitor, which often implies a programmer’s error, but I don’t think this is enough to motivate such a restriction.

0
source

Source: https://habr.com/ru/post/951185/


All Articles