java多线程中,关于Thread类的join()方法释放锁的一些问题

【精选】JAVA多线程:狂抓 join()方法到底会不会释放锁,给你彻底介绍清楚(三)_join会释放锁吗-CSDN博客

java线程join方法会释放锁吗_wait和join哪个会释放锁_王者生辉的博客-CSDN博客

关于join()方法是否释放锁的问题搜了一下,大概看了这两篇文章,但是感觉都没有提到我理解的那个点,结合源码和自己的理解,补充一下。

首先join()方法调用的是native方法wait(),wait()方法是释放锁的。那么关键就是释放的什么锁?

public class JoinTest {
    public static void main(String[] args) {
        Object object = new Object();
        MyThread myThread = new MyThread("MyThread", object);
        myThread.start();

        synchronized (myThread){
        //synchronized (MyThread.class){
        //synchronized (object){
            for (int i = 0; i < 100; i++) {
                if (i == 20){
                    try {
                        System.out.println("myThread start join");
                        myThread.join();
                        System.out.println("myThread finish join");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + i);
            }
            System.out.println("main方法执行完毕!");
        }
    }
}

class MyThread extends Thread {

    private String name;
    private Object object;

    public MyThread(String name, Object object) {
        this.name = name;
        this.object = object;
    }

    @Override
    public void run() {

        synchronized (this){
        //synchronized (MyThread.class){
        //synchronized (object){
            for (int i = 0; i < 100; i++) {
                System.out.println(name + i);
            }
        }
    }

}

还是这一个典型的案例,测试发现无论锁是object还是类.class对象,都无法释放造成死锁,这是什么原因呢?

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;
        }
    }
}

查看源码可以发现:join方法是synchronized方法,静态方法的锁是当前类的Class对象(类名.class),非静态方法的锁就是当前对象。

所以native方法wait()释放的锁只能是当前对象,其他的锁都释放不了,所以会造成死锁。