aspose file tools*
The moose likes Threads and Synchronization and the fly likes Why does notifyAll cause deadlock ? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Why does notifyAll cause deadlock ?" Watch "Why does notifyAll cause deadlock ?" New topic
Author

Why does notifyAll cause deadlock ?

Vishal Mungi
Greenhorn

Joined: Mar 24, 2005
Posts: 24
Why does below snippet hang when i replace as.notify with as.notifyAll in main ?

public class abc {

/**
* @param args
*/
public static String as = new String("");
public static void main(String[] args) {
new Thread(new b()).start();
new Thread(new a()).start();
new Thread(new c()).start();
synchronized (as) {
as.notify();
}
System.out.println("Main khatam");
}

}


class a implements Runnable{
public void run(){
synchronized (abc.as) {
try {
abc.as.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

try {
Thread.sleep(new Double(Math.random()*1000).longValue());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("A");
synchronized (abc.as) {
abc.as.notify();
}
}
}

class b implements Runnable{
public void run(){
synchronized (abc.as) {
try {
abc.as.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

try {
Thread.sleep(new Double(Math.random()*1000).longValue());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("B");
synchronized (abc.as) {
abc.as.notify();
}
}
}

class c implements Runnable{
public void run(){
synchronized (abc.as) {
try {
abc.as.wait();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

try {
Thread.sleep(new Double(Math.random()*1000).longValue());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("C");
synchronized (abc.as) {
abc.as.notify();
}
}
}
Edward Harned
Ranch Hand

Joined: Sep 19, 2005
Posts: 291

You need to read the thread tutorial from sun.

You're synchronizing on the wrong object (as). There are no threads associated with the object, as.

Read and follow the examples in the tutorial.


Ed's latest article: A Java Parallel Calamity http://coopsoft.com/ar/Calamity2Article.html
Vishal Mungi
Greenhorn

Joined: Mar 24, 2005
Posts: 24
All the three threads have been synchronized on the String object "as" which is a part of the class containg Main. This has been done to achieve
a sequential invokation of the threads in order they were started , no matter how much time each takes. This works fine with notify , but notifyAll
causes all the threads to wake up & all i know is that the program hangs .. whats happening ?
Edward Harned
Ranch Hand

Joined: Sep 19, 2005
Posts: 291

If you do weird things, weird things happen.

Your main() and the threads use multiple sync() on object as. Use a profiler to pinpoint the lock contention. No one would try to do what you are doing in real life.

notify() wakes up a single thread. Therefore, there is no contention between threads a, b, and c.

notifyAll() wakes up all the threads, a, b, and c, therefore, there is contentions between all the threads.

If you want to communicate properly between threads then pass the main() object to the new threads and use that to notify() the main. Use the new thread object to notify() the thread.

b threadb = new Thread(new b(this))
threadb.start();
threadb.notify();

If you're trying to create a thread pool, then use the thread pool API.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Originally posted by Vishal Mungi:
All the three threads have been synchronized on the String object "as" which is a part of the class containg Main. This has been done to achieve
a sequential invokation of the threads in order they were started , no matter how much time each takes. This works fine with notify , but notifyAll
causes all the threads to wake up & all i know is that the program hangs .. whats happening ?


Your code does not achieve what you describe regardless of whether or not you use notify() or notifyAll(). The first Thread you invoke start() on is not necessarily the first thread to begin execution. All three will likely at some point be contending for the monitor for as. The first thread to acquire this monitor will then enter the synchronized block and call wait(). This will release the monitor and add it to the wait set. At this point there may be 0, 1, 2 or 3 threads contending for the monitor. Even if there are none contending for it yet, it won't be long before at least one is, and at that point one of the other two threads will acquire the monitor for as and enter the synchronized block where it will invoke wait() as well. It will be added to the wait set, which at this point will now have two threads in it, and will release the monitor. The third thread will at this point either not have started execution yet or will be trying to acquire the monitor. Once it does that it too will invoke wait() and be added to the wait set. Now, at some point during all of this the main thread will be contending for the monitor as well. Once the main thread acquires the monitor it will invoke notify() which will remove one thread from the wait set and release the monitor. None of the order here is guaranteed, there could be 0, 1, 2 or 3 threads in the wait set. If none of the three threads you started are in the wait set yet then the main method will complete and those three threads will be left waiting indefinitely. Otherwise one thread will be removed from the wait set and resume execution. The first thing it will have to do is acquire the monitor. Of course, at this point it could be competing with other threads that haven't even reached wait() yet. Once it does it will leave the synchronized block and then sleep for a random amount of time. Once it wakes up it will print a line and attempt to acquire the monitor again. Once it acquires the monitor it will invoke notify() and remove one thread from the wait set, if there are any in it to begin with, and then finish execution.

So what you need to realize here is that your code is NOT guaranteed to execute in any particular order and is inherently deadlock prone as there's no guarantee one or more threads won't be left in the wait set.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
In other words there is absolutely no way of guaranteeing the order these will happen:

Thread A invoking wait().
Thread A invoking notify().
Thread B invoking wait().
Thread B invoking notify().
Thread C invoking wait().
Thread C invoking notify().
Main thread invoking notify().

All of that could happen in just about ANY order. The only thing you can guarantee is that no given thread will invoke notify() before that same thread has invoked wait(), that's obviously impossible. However it could very well happen like this:

Main thread invokes notify().
Thread A invokes wait().
Thread B invokes wait().
Thread C invokes wait().

In which case it would hang indefinitely. Or it could just as easily happen like this:

Thread B invokes wait().
Main thread invokes notify().
Thread B invokes notify().
Thread A invokes wait().
Thread C invokes wait().

In which case it wiould hang indefinitely again. There's no guarantees and you can come up with many many more examples where it would deadlock.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Why does notifyAll cause deadlock ?