• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Why does notifyAll cause deadlock ?

 
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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();
}
}
}
 
Ranch Hand
Posts: 291
Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Vishal Mungi
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 291
Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 1078
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 1078
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
PI day is 3.14 (march 14th) and is also einstein's birthday. And this is merely a tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic