大家好,我是徒手敲代码。
今天来介绍一下 Java 中的死锁。
什么是死锁?
在程序执行的过程中,两个或以上的线程,因争夺有限资源而彼此陷入等待,没有人愿意先作出让步,进而导致所有相关线程都无法继续推进。
举个例子,教室里的两个人,A 和 B,A 手上拿着两支笔,B 手上拿着两张试卷。每个人都必须同时拥有笔和试卷,才能写作业。但是双方都不肯先让步,A 要求 B 先给出试卷,而 B 要求 A 先给出笔,那么最后的结果,只能是两个人一直互相消耗。
产生死锁的四个条件
产生死锁,这几个条件缺一不可:
- 互斥条件:每一项资源在同一时间只能被单一线程独享。
- 占有并等待:线程持有至少一项资源,同时又提出新的资源请求,被拒绝后选择一直等待。
- 不可抢占:一旦资源被分配给某个线程,除非该线程自愿释放,否则外界无法强制回收。
- 循环等待:线程之间形成环路,每个都在等待环中下一个线程持有的资源。
打破死锁
要解决死锁,思路就是打破产生死锁的条件。下面列举一些常见的策略:
- 预先一次性分配资源:在线程启动的时候,分配好所有必需的资源,确保线程只在资源齐全的情况下,才开始执行。但是,可能会导致资源闲置的问题,降低了资源的整体利用率。
- 按顺序分配资源:为所有资源设定明确的分配顺序,要求所有线程遵循这一顺序来获取资源。例如,若线程需访问资源 X 和 Y,无论先访问哪个,后续都按既定顺序进行。这破坏了“循环等待”的可能性。比如,可以定义一个全局的资源排序规则,引导线程按序请求资源。
- 限时资源请求:在请求资源时采用超时机制,在线程尝试获取资源时,设定一个等待时间上限。如果超时,则主动放弃并可选择重试或异常处理,比如:锁的
tryLock(long time, TimeUnit unit)方法。 - 动态资源回收:在检测到某线程长时间阻塞等待资源时,主动从其手中收回已分配的资源,允许这个线程重新申请获取。
- 死锁检测与响应机制:使用死锁检测算法,一旦发现死锁,就采取措施,比如中断部分线程或回滚线程,以解除死锁状态。
在实际编程中,需要合理地设计资源分配策略、使用有序的资源申请顺序,或者设置合适的资源申请超时时间,来有效地避免死锁。
今天的分享到这里结束了。
关注公众号“徒手敲代码”,免费领取腾讯大佬推荐的Java电子书!