Win a copy of Java 9 Revealed this week in the Features new in Java 9 forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Why wait and notify from synchronized context?  RSS feed

 
raja singh kumar
Ranch Hand
Posts: 179
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am aware that wait and notify need to be called from synchronized context and a thread needs to have the lock to call wait or notify. Otherwise there will be illlegalmonitor exception.

My question is what would be the ill-effect if illegal monitor exception was not being thrown when it was being developed by the founder? What harm would it cause in that case?
 
Henry Wong
author
Sheriff
Posts: 23026
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That is simply how it is done. If you look at other threading environments, such as POSIX threads, Solaris threads, Windows threads, etc., all of these environments require that a mutex lock be held for the condition variable. And in all of these cases, there is a tight integration between the mutex lock and the condition variable.

So, with Java, the two implementations (synchronized with wait/notify *and* ReentrantLock with Condition) both also have this requirement.


And the reason is because there is a race condition. There is no way to guarantee that a notification won't be lost between a check for the state, ie. determining that a notification should be waited for, and actually waiting for the notification. Hence, all threading environments integrate these two features at a lower layer (to implement the guarantee).

Henry
 
raja singh kumar
Ranch Hand
Posts: 179
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Suppose a thread which does not hold the monitor for an object calls a notifyAll() on that object. Say there are 99 other threads who are waiting for that monitor. Now out of the 99 threads one will get the monitor whereas the monitor may not be available since it was a false notifyAll(). So how is a false notifyAll() going to cause an issue?
 
Henry Wong
author
Sheriff
Posts: 23026
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
raja singh kumar wrote:Suppose a thread which does not hold the monitor for an object calls a notifyAll() on that object. Say there are 99 other threads who are waiting for that monitor. Now out of the 99 threads one will get the monitor whereas the monitor may not be available since it was a false notifyAll(). So how is a false notifyAll() going to cause an issue?


Not sure where you are going with this? Are you trying to find a use case where it may not be a problem? ... and hence, conclude that it is not necessary? Remember the library needs to be useful (or it won't be used... ). I am sure you can dig up a use case where it may not cause a problem, but that doesn't mean that it is all that useful.  And what do you mean by "false Notify()"?

Anyway, give me a few minutes, I will write up the issues related to this in another post.

Henry
 
Henry Wong
author
Sheriff
Posts: 23026
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Okay, the question here are (1) why does the wait and notify mechanism needs to be from a synchronized context?, and (2) why is the waiting and notify mechanism checking it?

To start, the notification needs to based on state. In other words, you have to have a reason to send or wait for the notification. It doesn't make sense otherwise.  Of course, you can argue, why can't I just use wait/notify? ... well ... Technically, a blind notification is possible, but I would argue that this is really really in the minority, and really shouldn't be done that way regardless. We can have this as a separate debate, if you want, later.... in summary, the wait and notify mechanism needs to be synchronized, because it needs to be sharing state.

Next, why does the mechanism need to check that it is synchronized? Well, because it needs to release the lock. Keep in mind that one of the threads will be waiting for the notification. If this thread doesn't release the lock, then how is the sender going to send the notification, since it can't get the lock? So, this is where the race condition happens.

Well, to release the lock, one option is ... The programmer can simply move the waiting call outside the synchronized block, basically, have the code before and after it synchronized, but not the wait call itself. Unfortunately, this setup is not atomic. It is possible for notifications to be sent during this transition. And when this happens, it is possible for notifications to be lost.... so, these transitions (releasing and reacquiring the locks) needs to be atomic, which means that the releasing and waiting must be together. And since the wait method call releases the lock, it must also check to see if it is holding the lock.

... but ... we are not done yet. There are a few other points. Additionally...

One. Synchronized locks are reentrant. This means that it may be held more than once. The setup not only needs to release the lock, it needs to release it as many times that it is being held. Likewise, it needs to reacquire it as many times as it was released. This can't be done by Java code via synchronized, as there is no way the application would even know the lock count.

Two. The synchronized and wait/notify mechanism is implemented natively.... meaning the JVM uses their OS counterparts under the covers (with all modern JVMs). And this is simply how it is done it all forms of mutex locks and condition variables (that I know of). This means, if it didn't follow common practice/standards, it would have to be implemented by the JVM without using the OS library. It also means that the designer of the language decided to not follow what the industry is doing. I guess this can be done, but why?

Henry
 
raja singh kumar
Ranch Hand
Posts: 179
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And what do you mean by "false Notify()"?

By false notify(), I mean a thread not holding the monitor but calling notify() whereas the monitor for that object might be held by some other thread which may be currently using that object


Not sure where you are going with this? Are you trying to find a use case where it may not be a problem? ... and hence, conclude that it is not necessary? Remember the library needs to be useful (or it won't be used... ). I am sure you can dig up a use case where it may not cause a problem, but that doesn't mean that it is all that useful. 

Actually yes. Actually it would be utter chaos if  threads not holding the lock call notify or wait. It would be unnecessary waste of CPU if threads keep calling wait and notify without holding the monitor. Never thought about the waste of CPU processing. Now I am clear.


 
Richard Hayward
Ranch Hand
Posts: 160
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I found this an interesting question as I've been experimenting with these issues as well.
raja singh kumar wrote:By false notify(), I mean a thread not holding the monitor but calling notify() whereas the monitor for that object might be held by some other thread which may be currently using that object

When a thread invokes notify on an object, it may not exit synchronized code immediately anyway. Here, LockerThread acquires a lock on object o, then invokes o.notifyAll(), but sleeps for another second before exiting the synchronized block.
The main thread, which was WAITING on o, on receiving the notification, changes its state BLOCKED.

output:


Isn't that the same as the situation you have in mind, where a thread waiting on an object receives notification, but the object lock isn't available?
 
Henry Wong
author
Sheriff
Posts: 23026
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
raja singh kumar wrote:
And what do you mean by "false Notify()"?

By false notify(), I mean a thread not holding the monitor but calling notify() whereas the monitor for that object might be held by some other thread which may be currently using that object


As mentioned by Richard (in his longer discussion, which earned a cow... ), notify() just means that a thread get the notification -- it doesn't mean that the thread can run. The documentation specifically mentions that notify() wakes up a single thread, and notifyAll() wakes up all the threads. Perhaps, this implies that it runs immediately, but ... oh well...

Regardless, there is nothing "false" about the notify(). The notification is sent, and the targeted thread is no longer in the waiting state (ie. now in the blocked state).

Henry
 
Henry Wong
author
Sheriff
Posts: 23026
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
raja singh kumar wrote:
Actually yes. Actually it would be utter chaos if  threads not holding the lock call notify or wait. It would be unnecessary waste of CPU if threads keep calling wait and notify without holding the monitor. Never thought about the waste of CPU processing. Now I am clear.


And of course, the already mentioned race condition... ... which means that notifications can be lost; and that notify() may not actually wake up one thread and/or notifyAll() may not wake up all of the threads; and the many undefined behaviors that may occur due to the race conditions. etc.

Henry
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!