Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why object is not lock while thread is in runnable status?

I have class Run. Is simple, just prints , sleeps and then prints;

    public class Run implements Runnable {

    @Override
    public void run() {
        System.out.println("START RUN");
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("FINISH RUN");
    }
}

Ok now I'm writing test;

public static synchronized void main(String[] args) throws InterruptedException {

        Run r = new Run();
        Thread t = new Thread(r, "TEST");
        t.start();

        // EXECYTE THE CODE WHULE THREAD "TEST" IS RUNNABLE 
        synchronized (t) {
            System.out.println(t.getState());
            t.wait();
        }
        System.out.println("Y");

        // SLEEP THREAD "TEST" TO BE EXECUTED DURING THE TIME
        Thread.sleep(100);
        synchronized (t) {
            System.out.println(t.getState());
            t.wait();
        }
        System.out.println("Y2");
    }

Question 1: While thread "TEST" is executing I try to wait(). At this moment thread status is "RUNNABLE". Because of this status it does not wait, I do not understand why? if the status will be "TERMINATED" or "NEW" wait() works; if I remove t.start(), thread status will be "NEW" so wait works too. Could you tell me what happens?

OUTPUT:

START RUN
RUNNABLE
FINISH RUN
Y
TERMINATED`
like image 409
grep Avatar asked Dec 24 '22 07:12

grep


1 Answers

This is rather poorly documented. The javadoc of Thread#join(long) states

As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

It's specifically saying don't do what you are currently doing. That is, synchronized on a Thread object and calling wait on that same object.

synchronized (t) {
    System.out.println(t.getState());
    t.wait();
}

In the current execution of your code. Your main thread reaches the t.wait() invocation above while your TEST thread is sleeping. TEST then wakes up and terminates. As it terminates, it calls notifyAll waking up your main thread from the t.wait().

When your main thread then reaches the second t.wait(), there's nothing left in your program to wake it up, so your program just hangs.


All this to say: don't use Thread object monitors for anything.

like image 136
Savior Avatar answered Feb 02 '23 22:02

Savior