死锁的成因以及解决方案(简析)

文章讨论了死锁产生的原因,包括线程加锁后的未释放、可重入锁与不可重入锁的区别,以及通过哲学家吃面的例子解释多线程多锁的死锁场景。文章指出了形成死锁的四个必要条件,并提出通常通过破坏循环等待条件来解决死锁问题,而银行家算法在实际中应用较少。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.为什么会产生死锁?

二.死锁产生的几个场景

一个线程一把锁的情况

关于可重入和不可重入锁的简单举例

两个线程两把锁的情况

多线程多把锁

 如何解决死锁


一.为什么会产生死锁?

简单来说,就是进程加锁之后,没有被解锁而处于一直等待的状态

二.死锁产生的几个场景

一个线程一把锁的情况

如果单个线程被连续加锁两次及以上,成为了不可重入锁,那么该线程就造成了死锁(一般的synchronized是可重入锁,不会造成死锁)

关于可重入和不可重入锁的简单举例

public class syn{
	public synchronized void do1(){
		System.out.println("执行1");
		do2();
	}
	public synchronized void do2(){
		System.out.println("执行2");
	}	
}

如果是不可重入锁,那么我们在执行完输出语句"执行1"之后,因为锁是任然在do1手中,没有释放,那么我们是不能执行do2(),这个语句的

但是如果是可重入锁,那么我们就能直接获取do2的锁,然后执行do2操作

两个线程两把锁的情况

线程一等待着线程二给自己释放锁,线程二等待着线程一给自己释放锁

多线程多把锁

经典案例:哲学家吃面

 总所周知,一般人吃面是需要两根筷子(用手抓就算了吧)

但是这里有五个哲学家(五把锁)对应着五个筷子(五个解锁)

如果出现一种比较极端的情况

大家都同时拿自己左手或者右手的筷子(同时都获取了一把锁)

那大家都吃不了(都解锁不了)

 所以总结一下,造成死锁的四个条件

1.互斥使用.锁A被线程1占用,线程2就用不了

2.不可抢占.锁A被线程1占用,线程2不能把锁A抢过来, 除非线程1主动释放锁

3.请求和保持.有多把锁,线程1拿到锁A后,不想释放锁A,还想拿到一个锁B

4.循环等待.线程1 等待 线程2释放锁,线程2 要释放锁得等待线程3 来释放锁,线程3 释放锁得等待线程1 释放锁

 如何解决死锁

一句话

破坏上诉四个条件的任意一个即可

但是条件一和条件二是锁的基本特性,没法改

条件三的话只要释放锁就行,但是在大多数场景下没办法直接释放

所以一般来说

我们都是破坏循环条件

对于上面的哲学家吃面的问题,我们就可以对筷子(锁)进行编号,控制哲学家们拿筷子的顺序,就能解决死锁

 教科书上一般采用银行家算法,但是现实中基本不太实用,有兴趣的同学自行了解本文不多赘述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值