上一篇聊了线程安全。
线程安全的主要解决办法是实现可重入函数。
而可重入函数中的六大特征中的第五点,则引入了线程锁的机制。
而锁的机制,则会引发死锁的风险。
是否会引发锁,这个在于锁的正确使用。
当然,还需要说明一点,并非只有线程会出现死锁,并发的进程,也会引发死锁。
当前除了线程锁,还有进程锁,还有更大规模应用场景下的分布式锁。当然本文只讲线程锁。
那么,什么情况下会引发死锁呢?
产生死锁有四个必要条件:
互斥条件:一个资源每次只能被一个线程使用
请求和保持条件:一个线程获得了一个资源并占用,又请求了另外一个资源
不可剥夺条件:一个线程已获得的资源在未使用完成之前,不能强势剥夺
循环等待条件:若干个线程之间形成一种头尾详解循环等待资源的关系
这四个条件都存在了,再加上不当的代码实现,在高并发的环境中,就有概率发生死锁。
死锁是致命的,那么,如何避免死锁呢?
既然四个条件未必要条件,那么只需要选择破坏其中一个或多个,就可以避免掉死锁了。
其中互斥条件是不可以破坏的,它是线程安全的基础。
其他三个条件,都是考虑去破坏的。
一、破坏请求和保持条件
方法可以是这样:
1、第一个方法,如果需要多个资源,则一次性全部申请,无法申请,则等待;
2、第二个方法,在逻辑允许情况下,在使用完一个资源后,则释放当前资源。
二、破坏不可剥夺条件
当需要多个资源,只获得了部分资源,无法获得其他资源时,则释放所有资源;
三、破坏循环等待条件
给所有资源进行线性排序标号,在程序请求资源时,按顺序获取和使用资源。