关于这个问题,大体有两种说法,一种是不释放锁,另一种是释放锁。这里直接说结论:当join前面的对象与synchronized一致时,释放锁。否则不释放。为什么呢?
首先这里需要简单说一下线程的创建和死亡,如下图:
如图可知,线程创建后,通过thread.satrt()方法启动线程,此时线程进入runnable状态,直到获取时间片进入运行状态到线程结束,这里不作赘述。重点说一下当run状态进入runnable状态时,当通过object.wait()方法时会释放锁,而其他进程得到锁得以执行,除非被notify唤醒进入lock pool不然就会一直等待。
其次,有了这一理论铺垫后,来说一下thread.join()方法底层是wait实现的,而wait是释放锁的,这从join的码源得以验证,如下图:
但是我们需要明确一点:.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释放锁
}
最后用一个例子来更具体的说明一下:
上图中main方法里join前面的对象与synchronized一致时,释放锁,其他线程得到锁,此时run执行输出0-99。
如果main方法里join前面的对象与synchronized不一致时则打印到20时,会一直等待,其他线程也得不到锁,不执行run,但线程也没有停止。