可重入锁
可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。
synchronized 和 ReentrantLock 都是可重入锁。
可重入锁的意义之一在于防止死锁。
实现原理实现是通过为每个锁关联一个请求计数器和一个占有它的线程。当计数为0时,认为锁是未被占有的;线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数器置为1 。
如果同一个线程再次请求这个锁,计数器将递增;
每次占用线程退出同步块,计数器值将递减。直到计数器为0,锁被释放。
关于父类和子类的锁的重入:子类覆写了父类的synchonized方法,然后调用父类中的方法,此时如果没有可重入的锁,那么这段代码将产生死锁(很好理解吧)。
例子:
比如说A类中有个方法
public synchronized methodA1(){
methodA2();
}
public synchronized methodA2(){
//具体操作
}
也是A类中的同步方法,当当前线程调用A类的对象methodA1同步方法,如果其他线程没有获取A类的对象锁,那么当前线程就获得当前A类对象的锁,然后执行methodA1同步方法,方法体中调用methodA2同步方法,当前线程能够再次获取A类对象的锁,而其他线程是不可以的,这就是可重入锁。
如果锁的计数器为2,执行过程中抛出异常,锁的计数器直接置为0,会直接释放锁!
应该是一个线程,如果执行同步代码块过程中抛出异常未捕获,会立即终止,退出同步代码块,并且释放锁,不会执行后续代码。
最核心的就是抛了异常,线程内部如果没处理,线程会直接停止!
死锁
在java中我们常常使用加锁机制来确保线程安全,但是如果过度使用加锁,则可能导致锁顺序死锁。同样,我们使用线程池和信号量来限制对资源的使用,但是这些被限制的行为可能会导致资源死锁。java应用程序无法从死锁中恢复过来,因此设计时一定要排序那些可能导致死锁出现的条件。
产生死锁的条件
产生死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生。
(1)互斥条件:进程要求对所分配的资源(如打印机&