Why does m2 () run first?

Below is the code. Output signal 1000, b = 1000. I don't understand why m2 () is triggered every time every time.

public class TT implements Runnable{
    int b = 100;

    public synchronized void m1() throws Exception {
        b = 1000;
        Thread.sleep(100);
        System.out.println("b =" + b);
    }

    public synchronized void m2() throws Exception {
        Thread.sleep(2000);
        b = 2000;
    }

    public void run() {
        try {
            m1();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        TT tt = new TT();
        Thread t = new Thread(tt);
        t.start();// m1() starts

        tt.m2();// m2() starts

        System.out.println(tt.b);
    }

}

      

+3


source to share


3 answers


the real reason is 1 keyword synchronized

.

The method m2()

acquires a lock on the instance TT

and then sleeps. In the meantime, the start of the thread takes effect and the method run()

tries to call m1()

. But m1()

must wait for the call m2()

to complete and release the lock.

Now, if a new thread is started and it manages to be called m1()

before the existing thread calls m2()

, you will see events in a different order. This is theoretically possible ... but unlikely on typical Java platforms. (Typically, the parent thread is not executed when it starts the child thread.)

What happens after the return m2()

will be determined by the output you see. Since you are accessing directly tt.b

(without any synchronization), the result is not theoretically predictable.




Basically, this just illustrates that sleep

this is the wrong way to schedule threads. If you want one event on one thread to happen before another event on another, threads must coordinate explicitly. Relying on sleep and impressive temporary effects (for example, thread.start()

usually a long time), you get unreliable behavior.

1 - Obviously this is a combination of things. But the real reason with the hacker sleep

doesn't work as expected is the keywords synchronized

.

+3


source


It takes some time for the thread to start . An existing thread that is already running has a big advantage, it already exists and only needs a lock, while another depends on creating a new thread before it can acquire the lock. A thread only needs to acquire a lock to win the race by closing another, a thread that does not need to be created from scratch is likely to get there first.



This is still a race condition and you shouldn't write code that depends on who gets there first.

+1


source


If you want tt.m2 () to run after exits t thread

. Add t.join()

after t.start()

. This forces the main thread to start after t

its completion .

+1


source







All Articles