aspose file tools*
The moose likes Threads and Synchronization and the fly likes Need help with synchrnoized/wait/notify mechanism! Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Need help with synchrnoized/wait/notify mechanism!" Watch "Need help with synchrnoized/wait/notify mechanism!" New topic
Author

Need help with synchrnoized/wait/notify mechanism!

Ivan Jouikov
Ranch Hand

Joined: Jul 22, 2003
Posts: 269
Basically what I'm trying to do is to implement a simple thread interaction in an applet:

I have a ThreadPaint - simply a thread that sits in the background and does the painting when we need it to. The way I accomplish this is:



(so basically we wait on a lock, which is just an external Object).

Now, here's the applet's update method:



So, pretty much we simply notify that paint thread when we need to update our stuff, and then we go on with our business... Seems simple, right?

Well, not so.

If you try debugging this - it works just perfect.

However, if you run this in realtime - it's horror. When we call notify(), apparently both the paint thread and our current thread release their locks on the "lock" Object... and now they begin cometing - and most of the time our main thread wins.

As a result, when we need to repaint the screen many times - it only gets repainted once or twice...

Any ideas on how to overcome this?
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18709
    
  40

Here are a couple of obvious problems...

- The PaintThread "g" variable is shared among multiple threads, but is not synchronized. You have a race condition with this variable.
- The call to the wait() method is blind. There is no mechanism to confirm that it actually needs to wait. You need to reconfirm, after you synchronize, since conditions could have changed.
- The return from the wait() method, also need to reconfirm. This is because there are other ways to return -- basically, you could get interrupted.

But as a side question. It has been years since I worked with applets, but what is wrong with simply using the repaint() mechanism?

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Ivan Jouikov
Ranch Hand

Joined: Jul 22, 2003
Posts: 269
Sorry for the delay, something came up.

The PaintThread "g" variable is shared among multiple threads, but is not synchronized. You have a race condition with this variable.


What race condition? There's only one thread that paints - it's got nothing to compete with!

The call to the wait() method is blind. There is no mechanism to confirm that it actually needs to wait. You need to reconfirm, after you synchronize, since conditions could have changed.


No mechanism to confirm that it needs to wait? It needs to wait by default. I don't want my paint thread to paint anything unless I tell it to - so that's why I ask it to wait.

- The return from the wait() method, also need to reconfirm. This is because there are other ways to return -- basically, you could get interrupted.


And I do get interrupted (which kind of pisses me off). But wait() shouldn't return unless I tell it to.. when the applet terminates I'll simply call notify() and set the stopped = true;

But as a side question. It has been years since I worked with applets, but what is wrong with simply using the repaint() mechanism?


Well nothing is wrong with it, it's just that I wanted to take that same repaint mechanism and stick in a separate thread; this way graphic-heavy applets wouldn't bug down the performance.

_________________________

Also, the original problem of my post referes to the first quote in this message - why the hell does the race condition exist even if I notify() while inside a synchronized block?
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18709
    
  40

What race condition? There's only one thread that paints - it's got nothing to compete with!


The paint thread is competing with the thread(s) that is calling the update method.

Here are a couple simple race conditions:

1. Paint thread is drawing. Another thread calls update, which sets the g variable. The notification is sent, but is ignored because the paint thread is not waiting. The paint thread finishes, clears the g variable, and waits. In this case, the g variable set by the update thread is lost.

2. Paint thread just finished drawing, and is about to wait. It clears the g variable, but loses out to the other thread in getting the syncrhonization lock. The update thread sets the g variable, and sends a notification. This notification is lost because the paint thread is not waiting. The paint thread then grabs the lock and calls wait. In this case, the g variable is set correctly, but the paint threads waits anyway.

This gets much more complex when there are more than one updating thread.

No mechanism to confirm that it needs to wait? It needs to wait by default. I don't want my paint thread to paint anything unless I tell it to - so that's why I ask it to wait.


See example 2, race condition, above. The g variable is set correctly, but the paint thread incorrectly waits, when it should not.

Henry
[ June 10, 2005: Message edited by: Henry Wong ]
Ivan Jouikov
Ranch Hand

Joined: Jul 22, 2003
Posts: 269
Ohhhhhhh

Now I understand it. Thanks for showing me the light of Jesus

It's wierd how I couldn't work that out myself. Do you have any suggestions for a solution?

I can think of some boolean variable that indicates that another update was requested (which would be turned off as soon as the paint thread begins working. My head hurts too much right now to think, can you suggest something?

Thanks again!
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18709
    
  40

I can think of some boolean variable that indicates that another update was requested (which would be turned off as soon as the paint thread begins working. My head hurts too much right now to think, can you suggest something?


It's not that simple because you have a ton of issues that you have not dealt with. Namely:

1. You can't modify or use the g variable outside of synchronization, or you'll have a race condition. The "g=null" statement must be moved inside of the synchronization block.
2. This is a problem with painting because it is used throughout the whole operation. This needs to be modified to use a copy instead.
3. You can't just wait, as it is possible you have an another request pending. See next issue.
4. You can't just return from wait as you could have been interrupted. Issue 3 and 4 can be solved with a while loop check.
5. You can't assume that the update method can store the result as there could be a queue of requests backed up. You actually have to store the requests in a collection instead of a variable.

Anyway... to put it all together. The update could be modified as:



And the paint thread could be modifed as:



BTW, gList is a List collection. It doesn't have to be thread safe. And gCopy is a Graphics variable.

Henry
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18709
    
  40

BTW... a few more points.

I know that if you use Swing components, this is kinda moot. All operations must be done from the event dispatching thread anyway -- so all this hoop jumping will be doing is passing the requests back. There may also be some issues with AWT, but I am not a windowing system/graphics expert.

Another issue is that the repaint() mechanism may consolidate redraw requests. Something that is not implemented with your system.

Henry
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Need help with synchrnoized/wait/notify mechanism!