The Artima Developer Community
Sponsored Link

Legacy Java Answers Forum
June 2000

Advertisement

Advertisement

This page contains an archived post to the Java Answers Forum made prior to February 25, 2002. If you wish to participate in discussions, please visit the new Artima Forums.

Message:

Another answer.

Posted by Andrae Muys on August 04, 2000 at 2:13 AM

> Hi Javamates,
> I have one question to ask you people.
> In the class "Thread" all the relevant methods are there except
> "wait()and notify()".These methods are present in class "Object"
> I would like to know why "sun people" made this type of arrangement.

The simple answer to this is "Because that's where they belong", however
that probably isn't very useful. :)

The key to understanding this is understanding what wait() and notify()
are for.

wait() and notify() are Java's synchronisation primitives. A Thread
object encapsulates an independent running task. This task can access
any object in the JVM (within the security model at least). Unfortunately
so can any other task, and this introduces race-conditions. You prevent
race-conditions by serialising access to the resource/object that is
being shared. This is called Mutual Exclusion, and is provided by a
special mutex variable hidden inside Object. Locking/Unlocking this mutex
is the job of the synchronised keyword. Unfortunately this mutex often
needs to be unlocked while inside a synchronised region while the Thread
waits for some condition to occur (and then relocked before the task
continues). This is what wait() does. notify() allows another task to
signal that the condition has occured and therefore to wake up the waiting
thread.

Consider a quick example (most of the implementation has been left out)

public class Stack {
private LinkedList queue = new LinkedList();
private int maxSize = 10;
private int size = 0;

public void Push(Object in) {
// Both Push and Pop may be called at the same time, and so
// both the size and the top element may be changing while
// this is called. If we don't ensure Mutural Exclusion here
// we might end up checking the old size and the new Head or
// visa versa. Mutex is provided by synchronised, which locks
// the mutex of the enclosing object, in this case Queue.mutex.
// NB. Queue.mutex is in fact inherited by Object, and remains
// private to Object so we can't directly manipulate it.
synchronised(queue) {
// Note that any thread might be using this class, so the
// only thing we *know* they share in common is *this* object
// Hence the mutex is locked on the Object, not the Thread.
// Note the while loop. Because wait() relocks the mutex
// if another thread holds the lock when notify() is called
// it might be some time before wait() can return. In this
// time it's possible for another Push or Pop to have changed
// size again, so we *must* check the condition again and not
// assume that just because we are awake we can continue.
while (size == maxSize) {
queue.wait();
}
queue.addFirst(obj); // I consider the lack of a prepend operation to List to be a bug!
size++;
queue.notifyAll();
}
}
public Object pop() {
synchronised(queue) {
while (size == 0) {
queue.wait();
}
size--;
queue.notifyAll();
return queue.removeFirst();
}
}
}

Notice the use of notifyAll()! Always use notifyAll unless profiling
has determined that it is a performance bottleneck AND performance is
inadequate AND you have checked VERY VERY VERY carefully that you won't
face deadlock if you just notify one. Be aware that the above code WILL
deadlock if the notifyAll's are replaced with notify()'s AND UNLESS
YOU CAN EXPLAIN WHY YOU MOST CERTAINLY ARE NOT GOING TO BE ABLE TO
SATISFY THE THIRD CONDITION FOR USING NOTIFY()!



Replies:

Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2009 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us