关于这个问题,大体有两种说法,一种是不释放锁,另一种是释放锁。这里直接说结论:当join前面的对象与synchronized一致时,释放锁。否则不释放。为什么呢?

首先这里需要简单说一下线程的创建和死亡,如下图:

java 自动释放连接_加锁


如图可知,线程创建后,通过thread.satrt()方法启动线程,此时线程进入runnable状态,直到获取时间片进入运行状态到线程结束,这里不作赘述。重点说一下当run状态进入runnable状态时,当通过object.wait()方法时会释放锁,而其他进程得到锁得以执行,除非被notify唤醒进入lock pool不然就会一直等待。

其次,有了这一理论铺垫后,来说一下thread.join()方法底层是wait实现的,而wait是释放锁的,这从join的码源得以验证,如下图:

java 自动释放连接_多线程_02


但是我们需要明确一点:.wait()是Object下的方法,而.join()是Thread的方法,这就出现了一个问题,join通过wait实现,释放锁,那么释放的是哪个锁,是Thread还是Object呢?(注意这里Object是对象)那么我们需要知道,synchronized可以对某个对象加锁。

如下代码:实例化对象,只对对象加锁,这个对象不论在那个方法里锁住的只是这个对象。

private Object lock1 = new Object();

private Object lock2 = new Object();

public void test1(){

synchronized(lock1){

//互斥代码

}

}

上述代码只是对lock1加锁。这样,我们就得出结论,当join前面的对象与synchronized一致时,释放锁。否则不释放。

synchronized(obj){
thread.join(); //join不释放锁
}
synchronized(thread){
thread.join(); //join释放锁
}

最后用一个例子来更具体的说明一下:

java 自动释放连接_main方法_03


java 自动释放连接_多线程_04

java 自动释放连接_main方法_05

上图中main方法里join前面的对象与synchronized一致时,释放锁,其他线程得到锁,此时run执行输出0-99。

如果main方法里join前面的对象与synchronized不一致时则打印到20时,会一直等待,其他线程也得不到锁,不执行run,但线程也没有停止。

java 自动释放连接_java 自动释放连接_06


java 自动释放连接_java 自动释放连接_07