简体   繁体   中英

Thread execution sequence on synchronized block

In below code I'm trying to figure out threads handle execution on synchronized blocks:

public class ThreadExp {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable r = new MyRunnable();
        Thread t1 = new Thread(r, "Thread1");
        Thread t2 = new Thread(r, "Thread2");
        t1.start();
        t2.start();
    }

}

class MyRunnable implements Runnable {

    @Override
    public void run() {
        callFn();
    }

    private void callFn() {
        System.out.println(Thread.currentThread().getName() + ": entered callSync()");
        synchronized (Thread.currentThread()) {
            System.out.println(Thread.currentThread().getName() + ": inside sync");
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " leaving sync");
        }
        System.out.println(Thread.currentThread().getName() + ": leaving callSync()");
    }
}

Actual Output:

    Thread1: entered callFn()
    Thread2: entered callFn()
    Thread1: inside sync block
    Thread2: inside sync block
// 5000 millisec sleep
    Thread2 leaving sync block
    Thread1 leaving sync block
    Thread2: leaving callFn()
    Thread1: leaving callFn()

Whereas I expected something like:

Thread1: entered callFn()
Thread2: entered callFn()
Thread1: inside sync block
// 5000 millisec sleep
Thread1 leaving sync block
Thread1: leaving callFn()
Thread2: inside sync block
Thread2 leaving sync block
Thread2: leaving callFn()

Overall I thought Thread1 will acquire the lock then go to sleep. And only after Thread1 is finished, Thread2 can enter the synchronized block.

You are synchronizing on the thread itself:

synchronized (Thread.currentThread())

so each thread has its own lock and they can execute the synchronized block concurrently.

If you want the synchronized block to be run by only one thread at a time, you need to use the same lock.

In your example, it could simply be this , since the Runnable instance is the same for your two threads:

synchronized(this) {...}

The output will then look like:

Thread1: entered callSync()
Thread1: inside sync
Thread2: entered callSync()
Thread1 leaving sync
Thread1: leaving callSync()
Thread2: inside sync
Thread2 leaving sync
Thread2: leaving callSync()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM