路漫漫其修远兮,吾将上下而求索
一、死锁是什么
死锁是多个线程同时被阻塞,他们其中的一个或者全部都在等待某个资源被释放,由于线程无限期的被阻塞,因此程序不可能被正常终止~
二、死锁的成因
1.一个线程加锁两次
一个线程加锁两次,如果锁是不可重入锁就会造成死锁
2.两个线程两把锁
此时就算是可重入锁也会导致死锁~
举例:此时,你在家门口,但是钥匙锁在家里了,你打电话叫来开锁公司,开锁公司来了,他让你出示房产证,来证明房子是你的,否则不能给你开锁,你说你的房产证就锁在家里,你给我开锁,我就可以给你房产证证明,我说:你先给我开锁,我给你证明,开锁师傅说:你先给我证明,我才能给你开锁~ 这就很蛋疼了,两个线程互相向对方要对方的锁,这就造成了死锁
代码展现出来就是:
此时两个线程t1,先拿到了locker1锁,t2拿到了locker2锁(t1 t2 同时执行嗷),t1拿到locker1锁后,又要给locker2加锁,想要给lockler2加锁就得先释放locker2,但是locker2想要释放就得释放locker1锁让t2线程结束才能给你释放,此时两个线程互相要,就构成了死锁~
3.N个线程M把锁
哲学家就餐问题~ (这里是五个线程五把锁)
这里有五位哲♂学家,他们要吃饭,吃饭要拿两个筷子来吃,如果此时五位哲♂学家同时都拿起自己左手的筷子,那么一位哲♂学家手里只有一根筷子,并且每个哲学家拿到了就不放下这一根筷子了(只有拿到对应的两根筷子吃完饭才会放下)
此的二号哲♂学家手里拿到了一根筷子,但是另外一根被五号哲♂学家拿到了,自己没有两根筷子没法吃饭,三号,四号,都是这样,此时就构成了个循环,每个人都不能吃饭,就死锁了
三、死锁的四个必要条件
1.互斥使用:如果一个线程拿到锁,其他线程不能使用
2.不可抢占:如果一个线程拿到锁,这个锁只能这个线程自己释放,不能被其他线程强行占有
3.请求和保持:“吃着碗里的看这锅里的”即当资源请求者在请求其他资源的同时保持着原来资源的占有
4.循环等待:即存在一个队列:T1占用T2的资源,T2占用了T3的资源 T3占用了T1资源,每个线程不结束就不会释放资源,就会死锁
四、如何解决死锁问题
死锁的四个必要条件,既然是必要,那么我们破坏其中的一个条件就可以解决死锁问题,这里最容易破坏的就是循环等待~
具体怎么解决呢?拿上面的哲学家就餐问题来举例
我们就可以给筷子(制定一个加锁顺序,必须按照加锁顺序来加锁,否则就等待)
此时再次看这个问题,二号哲学家拿起了1号筷子,三号拿起了2号筷子,四号拿3号筷子,五号拿4号筷子,此时1号哲♂学家面前就只有5号和1号筷子,但是我们制定了规则必须按照顺序大小来加锁,所以此时一号哲♂学家就不会拿5号筷子了,那么五号哲♂学家就可以拿到一双筷子(4和5),他吃完了就放下筷子了,那四号就也可以拿到一双了,依次类推,最后一号哲♂学家等二号吃完之后放下了1筷子,此时他就也能吃饭了,这样就解决了死锁问题~~~!!!
这里映射到代码上其实很简单,只需要注意加锁的顺序就可以了~
写在最后
以上介绍本文的全部内容了,如果有任何问题欢迎私信改正或交流哦~欢迎大佬们.感谢您的支持