• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

strange results from wait() and notify()

 
Jarek Jankowski
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi guys,
I've written a class Printer that,I thought, will notify the "main thread" about the fact that it wrote a message onto a screen. However, the program doesn't behave as I expected. I expected to see results like this:

BBB
Another thread printed a message onto a screen
BBB
Another thread printed a message onto a screen
BBB
Another thread printed a message onto a screen
and so on(10 such pairs)

while I most often get:
BBB
BBB
.
.
.
(ten times)
Another thread printed a message onto a screen
Program complete.

I tried debugging it and observed strange Printer object's lock exchange between the two threads.

Could anyone please help? I really have no idea why it gives such results.

 
Henry Wong
author
Marshal
Pie
Posts: 21021
78
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Your wait() loop gives up the lock without calling wait(). This means that it is possible for the notify to be called without the thread waiting.

2. If a notification is sent, and no-one is waiting, the notification is lost.

3. Both of your threads are accessing the done flag, without any synchronization.

Henry
 
Jarek Jankowski
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Henry for your reply.
I understand and agree with your explanation in points 2 and 3.
As far as 1 is concerned, debugger showed me things that could justify your explanation. The main thread was very rarely on the Printer object's monitor. But how my wait() loop gives up the lock without calling wait()? I still don't how to fix this. Could you suggest some code changes so that I can undestand it thoroughly? Thanks.
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24208
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The synchronized block in main() should be around the loop, not inside. Then the only way that control is surrendered to the Printer thread is by calling wait(). Otherwise, the Printer thread can do whatever it wants when the control part of the loop is executing outside the synchronized block, and that's when notifications can be lost.

A multithreaded program will act completely differently under a debugger, because stepping in a debugger obviously changes the timing of everything by a lot!
 
Henry Wong
author
Marshal
Pie
Posts: 21021
78
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But how my wait() loop gives up the lock without calling wait()? I still don't how to fix this.


Take a look at your loop....



As you see, you have the synch block inside the while loop. And there are periods just before and just after the sync block, yet within the loop, where the thread doesn't hold the lock, and not calling wait(). The fix is, of course, to have the while loop inside the sync block.

Could you suggest some code changes so that I can undestand it thoroughly? Thanks.


Well, you also shouldn't be waiting blindly. It may be better to have some state on which thread is supposed to print -- which gets toggled back and forth as the two threads are printing.

Henry
 
Jarek Jankowski
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've done like you said but there is no improvement. Additionally, the main thread does not die (it doesn't print 'Program complete').
 
Henry Wong
author
Marshal
Pie
Posts: 21021
78
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've done like you said but there is no improvement.


That is because it is still possible for the printer to print "BBB", send the notification, release the lock, and then grab it back, repeat.

Sending the notification does not give the lock to the waiting thread. The printer can hold (release and regrab) onto the lock sending many notifications before the waiting thread gets it.

Additionally, the main thread does not die (it doesn't print 'Program complete').


This is caused by a race condition between setting the flag and the sync lock -- as it is possible for the waiting thread to get the lock between those two actions.

ie. --> Notification is sent. --> notification is recieved --> message is printed --> while loop checks for flag --> thread waits --> then the flag is set.

Henry
[ September 24, 2008: Message edited by: Henry Wong ]
 
Jarek Jankowski
Greenhorn
Posts: 13
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Now it is clear. Thanks Henry.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic