2

Thread 1:

if(!conditionFullfiled) this.wait();

Thread 2:

if(conditionFullfiled) thread1.notify();

I want to wake up thread 1 from thread 2, when some condition is fullfiled. But isn't there a problem, when thread1.notify() is called if(!conditionFullfiled) ***HERE*** this.wait(); ?

fhucho
  • 34,062
  • 40
  • 136
  • 186

4 Answers4

3

To do obj.wait() and obj.notify(), you need to own the monitor of the object you're going to wait/notify on. In your code, you probably don't want thread1.notify(). Example:

   Object someSharedObject = ...

Thread1:

   synchronized(someSharedObject) {
     // while NOT if for spurious wake ups.
     while(!conditionFullfiled) someSharedObject.wait();
   }

Thread2:

   synchronized(someSharedObject) {
     if(conditionFullfiled) someSharedObject.notify(); // this wakes thread1
   }

The synchronized lock is on someSharedObject (can be this), which means the two threads will never clash. .wait() releases the currently held monitor, so Thread2 will not be blocked when Thread1 is waiting.

Edit: I learnt something about spurious wake ups. The .wait() must be done in a while loop - if is not enough. Why do threads spontaneously awake from wait()? . Thanks Enno Shioji for teaching me.

Edit: Clarified .wait() releases monitor.

Community
  • 1
  • 1
Martin Algesten
  • 13,052
  • 4
  • 54
  • 77
  • `if` should be replaced by `while` to cope with spurious wake ups. – Enno Shioji Nov 28 '10 at 12:38
  • `someSharedObject.wait();` is called inside the synchronized block - doesn't that mean that Thread2 won't never enter into the other synchronized block, if Thread1 is already waiting? – fhucho Nov 28 '10 at 12:38
  • @fhucho, `wait()` releases the currently held monitors. – Martin Algesten Nov 28 '10 at 12:46
  • @Martin: "there really isn't anything that wake a thread up randomly" According to the spec, there is... I think the API doc of `wait()` should warn this. http://stackoverflow.com/questions/2540984/why-do-threads-spontaneously-awake-from-wait – Enno Shioji Nov 28 '10 at 12:54
  • @Martin Algesten thanks, will you please also add a mention about the fact that wait() releases all monitors? – fhucho Nov 28 '10 at 13:00
3

You have 2 problems here.

  1. you should not call wait() and notify() on thread object itself. Better way to do this is to use special lock object, e.g.

    private Object lock = new Object(); ...... lock.wait();

  2. The next problem is that you have to call both wait() and notify into synchornized block, i.e.

    syncronized(lock) { // some code lock.wait(); }

then in other place in code say:

syncronized(lock) {
    lock.notify(); // this line will cause the wait to terminate and the first thread to continue.
}

It is convenient to localize both wait() and notify() wrapping methods in one class, so they have access to lock object.

For more information read http://download.oracle.com/javase/6/docs/api/ http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html

AlexR
  • 114,158
  • 16
  • 130
  • 208
0

What object you use as "this"? If you invoke wait() on thread1 object, and both statements you have shown are wrapped in a loop like this:

new Runnable() {
    synchronized (thread1) {
        thread1.wait() 
    }
}

Then your code will work as you want. (First thread will halt when condition is false, and work otherwise). The trick is that interactions on the thread object are synchronized, so one thread can not interrupt while other is working with the object.

EDIT: It will be even better if you will synchronize not on the thread, but on some other object (you can simply create pure object to provide locks).

Rogach
  • 26,050
  • 21
  • 93
  • 172
0

No problem at all since wait releases object lock (in case this).

It's a best practice to guard wait/notify conditions in while blocks - to avoid spurious wake-ups.

Ovidiu Lupas
  • 185
  • 5