Why does the program below go into a dead end without sleep, but with sleep it executes all three threads and ends 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 any waiting thread to acquire the lock sequentially in no particular order, or can only one thread acquire the lock?

+3


source to share


3 answers


Without a sleep statement, the statement obj.exit();

will most likely execute before all of your threads have reached their sleep state. i.e. the call notifyAll

will complete before at least one of your threads is pending. This way, at least one of your threads will be stuck in a waiting state, waiting for some other thread to notify and wake up. But this will never happen, because obj.exit () has already completed.



With your sleep statement, all of your threads will be able to reach their wait state, and your notification call will be triggered after sleep wakes them all up. The wakeup order will not be deterministic and will be handled by the thread scheduler.

+3


source


Your code suffers from "lost notification" syndrome, which is facilitated (but not determined deterministically) by calling sleep

.

You have not provided any mechanism to ensure that exit

all threads have already reached their call at the time of the call wait

. Therefore, some threads will skip the notification and enter the eternal wait state.



The call notifyAll

invokes all waiting threads, but it does not wake up threads that will enter the wait state in the future.

+2


source


With the following code:

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

      

You start threads. Threads can take some time to start as it involves memory allocation and other operations. When your threads start, they enter a wait state. However, started threads are not immediately executed. They begin execution as soon as the scheduler decides it is time to execute them. When you call start

, the main thread is currently running on the CPU. Without sleep

, most likely, the main thread will keep the processor running and call:

obj.exit();

      

Before the threads actually started, that is, before the threads actually entered the wait state. notifyAll

will execute in vain since the threads have not started yet and therefore are not waiting. The notification will be lost.

When you call sleep, you will temporarily suspend the main thread (for a processor perspective). This means that other threads are more likely to acquire the CPU and enter a wait state. So when you call notifyAll

, this time the notification won't get lost. Note that there is no guarantee that this will happen: it may happen that when called, exit()

some (or all) of the other threads have not yet executed their own wait

.

+2


source







All Articles