Pranav
Pranav

Reputation: 826

Why the below program, without a sleep go to deadlock state but with sleep it executes all the three threads and terminates normally?

public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
    ExampleTest obj = new ExampleTest();
    Thread t1 = new Thread(new Runn(obj));
    Thread t2 = new Thread(new Runn(obj));
    Thread t3 = new Thread(new Runn(obj));
    t1.start();
    t2.start();
    t3.start();

    //Thread.sleep(1);

    obj.exit();

}

}

class ExampleTest {
public synchronized void enter() {
    try {
        System.out.println("printed " +Thread.currentThread().getName() +" inside wait");
        this.wait();
        System.out.println("printed " +Thread.currentThread().getName() +" exit wait");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("printed " +Thread.currentThread().getName() +" at time: "+System.currentTimeMillis());
}

public synchronized void exit() {
    this.notifyAll();
}

}

class Runn implements Runnable {
ExampleTest obj;

public Runn(ExampleTest obj) {
    this.obj = obj;
}

@Override
public void run() {
    obj.enter();
}

}

what is the role of notifyAll(). Will notifyAll() allows all the waiting thread to acquire lock sequentially in random order or only one thread can acquire the lock?

Upvotes: 3

Views: 131

Answers (3)

mziccard
mziccard

Reputation: 2178

With the following code:

t1.start();
t2.start();
t3.start();

You are starting the threads. Starting threads might take some time as it involves memory allocation and other operations. When your threads run they enter a wait state. Started threads do not, however, execute immediately. They start executing as soon as the scheduler decides it is time for them to execute. When you call start the main thread is currently running on the CPU. Without the sleep most likely the main thread will keep the CPU and call:

obj.exit();

Before the threads actually started, that is, before the threads actually entered the wait state. The notifyAll will execute in vain, as threads are not started yet and therefore are not waiting. The notification will be lost.

With the sleep call you are suspending the main thread for quite some time (for the CPU perspective). This means that the other threads will most likely get the CPU and enter the wait state. So when you then call notifyAll this time the notification will not get lost. Notice that there is no guarantee that this will happens: it might still happen that when you call exit() some (or all) other threads have not yet executed their wait.

Upvotes: 2

gipsy
gipsy

Reputation: 3859

Without the sleep statement the statement obj.exit(); will be very likely be executed before all of your threads reaching their wait status. ie. the notifyAll call will be over before at least one of your thread is in wait status. So at least one of your threads will be stuck in wait status waiting for some other thread to notify it and wake up. But that will never happen as obj.exit() is already finished.

With your sleep statement in place , all of your threads will get a chance to reach their wait status and your notifyAll call after the sleep will wake them all, The order of waking up will not be deterministic and will be handled by the thread scheduler.

Upvotes: 3

Marko Topolnik
Marko Topolnik

Reputation: 200206

Your code suffers from the "lost notification" syndrome, which is alleviated (but not deterministically avoided) by the sleep call.

You haven't provided any mechanism which would ensure that, at the time of calling exit, all the threads have already reached their wait call. Therefore some threads will miss the notification and enter an eternal wait state.

The notifyAll call does wake up all waiting threads, but it doesn't wake up threads which enter the wait state in the future.

Upvotes: 2

Related Questions