fhucho
fhucho

Reputation: 34530

Simple Java concurrency question

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(); ?

Upvotes: 2

Views: 191

Answers (4)

Martin Algesten
Martin Algesten

Reputation: 13620

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.

Upvotes: 3

AlexR
AlexR

Reputation: 115328

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

Upvotes: 3

Rogach
Rogach

Reputation: 27190

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).

Upvotes: 0

Ovidiu Lupas
Ovidiu Lupas

Reputation: 185

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.

Upvotes: 0

Related Questions