总结死锁的成因, 和解决方案

一、不可重入锁——死锁

1.概念


不可重入锁是”不可以重复进入的锁“,它不允许同一个线程连续多次获取同一把锁。当第一次线程A锁未释放,第二次线程A又要重新加锁的时候就要阻塞等待,显然此时线程A既不能获取到锁还必须一直阻塞等待,这就是所谓的”死锁“现象。

2.实现方式


在锁中记录该线程持有者的线程身份以及一个计数器(记录加锁次数),若果发现当前加锁的线程就是持有锁的线程,且计数器的次数为2时,立刻停止,这就出现了死锁。

问题:如何解决"死锁"现象?

答:加锁的时候判定一下,看当前尝试申请锁的线程是不是已经就是锁的持有者了,如果是,直接解锁放行~

注意:synchronized是可重入锁。

二、死锁(详细理解)


1.死锁的四个必要条件<同时满足>


①互斥作用——一个线程拿到一把锁之后,另一个线程不能使用。(锁的基本特点,原子性,为锁特征)

②不可抢占——一个线程拿到锁,只能自己主动释放,不能被其他线程强行占有。(不可挖墙脚,为锁特征)

③请求和保持——当一个线程占据多把锁后,除非显式释放锁,否则锁一直被该线程锁占用(碗里的锅里的都得到,为代码特征)

④循环等待——多个线程等待关系闭环了(房间钥匙锁车里了,车钥匙锁房间里,为代码特征)

2.死锁的三种典型情况


一个线程,一把锁,这把锁是可重入锁不影响,是不可重入锁会死锁。

两个线程两把锁,即使是可重入锁,也会出现死锁。

N个线程,M把锁,直接是死锁——”类比于哲学家就餐“。

哲学家就餐问题:假设有五个哲学家和五根筷子,随即进行吃面条(拿起两根筷子——加锁)和思考人生(放下筷子——解锁)两个行为;若想拿筷子但是发现筷子被别人占用了,就会阻塞等待(等待的同时不会放下手里已经占有到的筷子),若是五个哲学家同时拿起左手边的筷子,结果一个人都吃不到面条,这就是典型的”死锁“!

3.如何避免死锁


破坏循环等待——针对锁进行编号,如果需要同时获取到多把锁,约定加锁顺序(务必是先对小的编号加锁,后对大的编号加锁)

synchronized(locker1){
synchronized(locker2){
//........代码
}
}
//先对1号加锁,再对2号加锁,先释放1号的锁,2号的锁才能释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值