java線程之——join到底釋不釋放鎖

join是Thread類下的實例方法,其核心思想是:在誰的業務代碼裏調用,誰就等待!

舉個例子:

public class JoinThread implements Runnable {

    private final Object lock = new Object();

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        String state = Thread.currentThread().getState().toString();
        System.out.println(name + ":" + state);

        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + " .....................begin.");
            try {
                // Thread.sleep(3000); // 不讓CPU,不釋放鎖

                Thread.currentThread().join(3000); // 讓出CPU,釋放當前線程的對象鎖,但不釋放lock鎖

                // lock.wait(3000); // 讓出CPU,釋放鎖

                System.out.println(Thread.currentThread().getName() + " .....................end.");
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class TestJoin {

    public static void main(String[] args) {
        Runnable r = new JoinThread();

        Thread t1 = new Thread(r);
        t1.setName("Thread1");
        t1.start();

        Thread t2 = new Thread(r);
        t2.setName("Thread2");
        t2.start();
    }
}

執行結果:

Thread1:RUNNABLE
Thread1 .....................begin.
Thread2:RUNNABLE
Thread1 .....................end.
Thread2 .....................begin.
Thread2 .....................end.

可見,鎖是不釋放的,但是看join源代碼,會發現,其實現等待的原理是調用wait,我們知道wait方法是釋放鎖的,但爲啥上面例子卻沒有釋放鎖呢?其實很簡單,join方法是被synchronized修飾的,它本質上是一個對象鎖,也就是說,join方法本身會加鎖,其內部的wait方法調用也是釋放鎖的,但是它釋放的是當前線程的對象鎖,而不是外面的lock鎖。

    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章