1、什么是死锁?
死锁指一组互相竞争系统资源的进程/线程永久性地阻塞 (以下线程同进程)。当一组线程中的每个线程都在请求某些资源,而这组线程中被阻塞的其他线程已经占用了这些资源,没有其他任何线程会再释放出这些资源,于是就发生了死锁,死锁是永久的。
2、发生死锁的条件
死锁有三个必要条件:
①互斥。一次只有一个线程可以使用一个资源。
②占有且等待。当一个线程已占用了某些资源,在请求等待其他资源的时候,不释放已占用的资源。
③不可抢占。其他线程不能强行抢占线程已经占用的资源。
这三个条件是发生死锁的必要条件,而非充分条件。要产生死锁还需要第四个条件:
④循环等待。存在一个闭合的线程链,每个线程至少占有线程链中下一个线程所需的资源。
这四个条件构成了死锁的充分必要条件。
3、处理死锁的方法
3.1 死锁预防
死锁预防是试图设计一种方式来破坏构成死锁的一个条件。
1)互斥。这个条件是不能禁止的,如果需要对资源进行互斥访问,那么操作系统就必须支持互斥。
2)占有且等待。要求线程一次性地请求所有需要的资源,并阻塞这个线程直到所有请求都能满足。
使用账户转账的例子说明。示例代码1:
//资源分配器类,用于分配各账户进行转账操作时所需申请的锁资源
class Allocator{
//list容器保存资源对象
private List<Object> als = new ArrayList<>();
private Allocator(){
}
//单例模式,所有线程使用同一个资源分配器
private static Allocator instance = new Allocator();
public static Allocator getInstance(){
return instance;
}
//申请资源,也就是本账户对象this和目标账户对象target这两把锁
synchronized public boolean apply(Object from, Object to){
//当一个线程申请这两个资源时,发现容器中已经存在其中一个对象,
//说明其他对象已经占用了至少一个对象,那本次申请就不成功,因为不能一次申请全部所需资源
if(als.contains(from) || als.contains(to)){
<