线程在进入同步代码块、同步方法之前必定要获取同步监视器的掌控权,也就是当前同步监视器必须要先被之前的线程所释放.
那同步监视器在什么时候被线程释放?
当线程在以下情况会释放同步监视器
在同步方法、同步代码块中
- 两处执行完毕
- 线程调用线程wait()方法时,线程会释放当前所拥有的同步监视器
- 出现未处理的Error或者异常,当前线程被暂停,同时释放同步监视器
- 遇到break、return关键词时,代码块、方法被终止
当程序调用了线程的 sleep()、yield()方法时,当前线程不会释放同步监视器,调用suspend()方法时,线程被挂起,不会释放同步监视器
还有一种线程同步方式,使用同步锁机制实现线程同步(Lock)
在实现线程安全控制中,常用的同步锁为 ReentrantLock(可重入锁)
例如下面代码
private final ReentrantLock reentrantLock = new ReentrantLock();
public void method(double drowMoney){
//加锁
reentrantLock.lock();
try {
//需要保证线程安全的代码块
}catch (Exception e){
}
finally {
//通常使用finally代码块保证锁的释放
reentrantLock.unlock();
}
}
同步方法与同步代码块要求加锁和释放锁要同时出现在一个结构块中,获取多个锁时,需要以相反的顺序释放锁,
而ReentrantLock 具有可重入性线程可以对已被加锁的ReentrantLock 锁再次进行加锁,在调用lock()方法后,需要显示调用unlock()方法释放锁,而且ReentrantLock 提供了非结构块的 trylock() 、试图获取可中断 锁的lockInterruptibly()、获超时失效锁的trylock(long TimeUnit) 方法