一、简介
在之前的文章中,我们介绍了synchronized
同步锁关键字的作用以及相关的用法,它能够保证同一时刻最多只有一个线程执行修饰的代码段,以实现线程安全执行的效果。
但是如果过度的使用synchronized
等方式进行加锁,程序可能会出现死锁现象。
那什么是死锁呢?它有什么危害?
我们知道被synchronized
修饰的代码,当一个线程持有一个锁,其它线程尝试去获取这个锁未获取到时,那么其它线程会进入阻塞状态,直到线程释放锁才能再次拥有获取锁的条件。假如线程 A 持有锁 L 并且想获取锁 R,线程 B 持有锁 R 并且想获取锁 L,那么这两个线程将会永久等待下去,这种情况就是最简单的死锁现象。
如果程序出现了死锁,会给系统功能带来非常严重的问题,轻则导致程序响应时间变长,系统吞吐量变小;重则导致应用中的某一个功能直接失去响应能力无法提供服务,因此我们应该及时发现并避规这些问题。
当然发生死锁的软件应用,不仅限于 Java 程序,还有数据库等,不同的是:数据库系统中设计了死锁的检测以及从死锁中恢复的机制,数据库如果检测到一组事务中发生了死锁,将选择一个牺牲者并放弃这个事务。
而 Java 虚拟机解决死锁问题并没有数据库那么强大,在 Java 程序中,采用synchronized
加锁的代码如果发生死锁,两个线程就不能再使用了,并且这两个线程所在的同步代码/代码块也无法再运行了,除非杀掉服务,然后重