多线程之 死锁

死锁是啥

死锁: 是指的是两个或者两个以上的线程在执行的过程中,互相持有对方的资源并且不主动释放造成的恶性循环。

死锁的四个必要条件

1 互斥条件:线程对所分配的资源具有排他性,即一个资源只能被一个线程占有,直到这个资源被释放
2 请求与保持条件:一个线程因为请求被占有资源而发生阻塞的时候,对已经获得的资源保持不放。
3 不剥夺条件:线程已获得的资源,在其未使用完之前不能被强行释放,只能在自己使用完毕才能释放这个资源。
4 循坏等待条件:当发生死锁的时候所有的线程都会形成一个死循环,造成永久阻塞。

如何解决死锁

需要破坏四个必要条件之一就行。

预防死锁

1 破坏请求保持状态:资源的一次性分配,一次性分配所有资源就不会有请求了;只要又一个资源得不到分配,也不给这个进程分配其他资源;
2 破坏不可剥夺条件: 占有部分资源的线程进一步申请其他资源的时候,如果申请不到就自动释放自己占有的资源
3 破坏循环等待条件: 系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反
可以采用以下方法:
1 使用Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,设置超时时间,超时就退出,防止死锁
2 尽量降低锁的使用粒度,尽量不要几个功能使用一把锁

避免死锁

死锁预防和死锁避免的区别

死锁预防是设法至少破坏产生死锁的四个必要条件之一,严格的防止死锁的出现;而死锁避免则不那么严格的限制产生死锁的必要条件的存在,因为即使死锁的必要条件存在,也不一定发生死锁。死锁避免是在系统运行过程中注意避免死锁的最终发生。
 
银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。

死锁检测

1 Jstack命令
2 JConsole工具

死锁和活锁和饥饿的区别

1 死锁是:两个或者两个以上的线程在执行的过程中,相互想要对方的资源,但是不会主动释放自己的资源。
2 活锁是:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直尝试,失败,尝试,失败的过程。活锁可以自己打开的而死锁不能。
3 饥饿是:一个或者多个线程因为种种原因一直得不到想要的资源,导致一直无法执行。
如果线程T1占用了资源R,线程T2又请求封锁R,于是T2等待。T3也请求资源R,当T1释放了R上的封锁后,系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放了R上的封锁之后,系统又批准了T4的请求……,T2可能永远等待。
java导致饥饿的原因
1 优先级高的线程一直抢占低优先线程的资源,导致低优先级线程无法得到执行
2 线程被永久的阻塞在一个同步代码块的状态,因为其他线程总是能在他之前对该同步代码块进行访问

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值