10_活跃性问题
活跃性问题
一、死锁
1.1 死锁条件
- 互斥:资源是互斥的,只能被一个线程持有
- 占用且等待:线程占有一些资源后,在等待其他资源,等待过程中不会释放自己已占用的资源
- 不可剥夺:不可以强行剥夺已被线程占有的资源
- 循环等待:占用资源的线程在循环等待其他占用资源的线程释放资源
1.2 死锁避免
避免死锁的办法,就是破坏死锁的四个条件:
- 互斥:开放调用,减少锁范围,避免对方法加锁,避免获取多个锁
- 占用且等待:一次性获取全部资源,避免锁等待
- 不可剥夺:线程自己释放资源即可,比如超时释放锁,随机等待获取锁等
- 循环等待:对资源进行排序,有序申请占用资源
1.3 死锁诊断
- 代码分析
- 找出可能获取多个锁的代码区域
- 全局分析,确保获取它们获取锁的顺序是一致的,避免循环等待
- JVM 线程转储信息
- JVM 线程转储信息可以打印出死锁相关信息
二、饥饿
- 饥饿:线程由于无法访问它所需资源而不能继续执行时,发生饥饿
- 出现这种现象的情况有:
- 优先级使用不当
- 长时间持有锁不释放
- 解决饥饿的方案有:
- 避免使用优先级
- 使用公平锁,线程按先来后到执行,有序执行
- 超时释放锁,避免长时间持有锁
三、活锁
- 活锁:线程之间相互谦让,同时加锁资源又同时释放资源,导致没有线程可以执行
- 出现这种现象的情况有:
- 冲突后同时等待和重发,比如网络数据包,两台机器同时发包导致冲突,然后又等待同样的时间,再继续发包,又会冲突
- 过度的错误恢复,将不可修复错误当作可修复错误重复执行。比如,事务执行失败回滚,然后又重新执行,又失败回滚,一直循环
- 避免活锁的方案有:
- 随机等待时间,避免活锁的同时占用和同时释放资源,随机等待可以降低冲突