死锁的成因和解决方案
一、什么是死锁
简单理解就是:一个线程加锁之后,无法被解锁,导致程序无法正常运行。
二、死锁的成因
1、一个线程,一把锁的情况
一个线程连续加锁两次,如果这个锁是不可重入锁,那么一定会死锁!
synchronized是可重入锁,所以不会有这个问题~
2、两个线程,两把锁的情况
死锁场景:线程1先获取锁A,再尝试获取锁B,同时,线程2先获取锁B,再尝试获取锁A,此时两个线程就会互相僵住,谁都获取不到对方持有的锁。
一个简单的死锁代码:
public class Test {public static void main(String[] args) {//2个锁对象Object lockerA = new Object();Object lockerB = new Object();Thread t1 = new Thread(() -> {System.out.println("t1尝试获取锁A");synchronized (lockerA){System.out.println("t1获取到锁A");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1尝试获取锁B");synchronized (lockerB){System.out.println("t1获取到锁B");}}});Thread t2 = new Thread(() -> {System.out.println("t2尝试获取锁B");synchronized (lockerB){System.out.println("t2获取到锁B");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t2尝试获取锁A");synchronized (lockerA){System.out.println("t2获取到锁A");}}});t1.start();t2.start();}
}
代码运行结果:
因为锁A当前被t1所持有,锁B当前被t2所持有,在两个线程都没有释放锁之前,尝试获取对方所持有的锁,那么必然会出现死锁的情况~
这就好比,你把家里的钥匙落在了车里,车钥匙又被落在了家里~
3、多个线程多把锁的情况
2个线程都可能出现死锁的情况,那么多个线程的情况下更容易出现死锁~
哲学家就餐问题就是一个经典的多个线程死锁的场景~
三、如何避免死锁
产生死锁有4个必要条件:
(1) 互斥使用。线程1拿到锁A之后,线程2在锁A被释放之前就拿不到了。
(2) 不可抢占。线程1拿到锁A之后,线程2只能等线程1释放锁A,而不能把锁A抢过来。
(3) 请求和保持。线程1拿到锁A之后,还没释放锁A就想获取锁B。
(4) 循坏等待。线程1等待线程2释放锁,线程2等待线程3释放锁,线程3等待线程1释放锁...
既然以上4个条件是产生死锁的必要条件,那么只要打破其中一个条件,就不会产生死锁了~
其中,条件1和条件2都是锁的基本特性,我们无法干预~
条件3可以改变代码的写法,让线程1释放锁A之后再释放锁B,但这样可能会改变代码的执行逻辑,因此普适性不高。
只有条件4是我们有把握打破的~
我们可以约定好加锁的顺序,比如给每个锁进行编号,在加锁的时候,先加编号小的锁,再加编号大的锁,这样就可以有效避免循坏等待了~
比如,哲学家就餐问题的解决方案:
给每根筷子进行编号,并规定,先拿编号小的筷子,后拿编号大的筷子。
如上图,E就可以先拿到2根筷子吃面,E吃完后放下筷子,D就可以获取到2根筷子,D吃完后C获取到2根筷子……这样每个哲学家都能吃到面条,而不会出现死锁的情况。
死锁的成因和解决方案相关推荐
- 线程死锁的成因以及解决方案
线程死锁 一 . 什么是线程死锁 二 . 如何避免死锁 一 . 什么是线程死锁 线程死锁描述的是:多个线程同时被阻塞,他们中的一个或多个都在等待某个资源被释放,由于线程被无期限地阻塞,因此程序不可能正 ...
- mysql死锁解决方法_mysql出现死锁的原因及解决方案
mysql出现死锁的原因及解决方案 发布时间:2020-06-04 16:35:40 来源:51CTO 阅读:418 作者:三月 本文主要给大家介绍mysql出现死锁的原因及解决方案,文章内容都是笔者 ...
- 分布式架构-ZK分布式锁中死锁和羊群效应解决方案
分布式架构-ZK分布式锁中死锁和羊群效应解决方案 一.效果演示 有两个接口,GetTest2和GetTest3,分别都加上了@BxcZkLock注解,其中value 代表是否包含事物,如果是,则会在方 ...
- MySQL - 死锁的产生及解决方案
MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件 1.1 什么是死锁 1.2 死锁产生的4个必要条件 2. 死锁案例 2.1 表锁死锁 2.2 行锁死锁 2.3 共享锁转换为排 ...
- java排查死锁_Java死锁的排查和解决方案
相信程序员都会碰上这样的问题,Java死锁如何排查?又如何解决呢?那么,何为死锁呢?死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象.今天小编一次性来帮助大 ...
- 死锁的成因和对应的解决方案
目录 一.什么是死锁 二.产生死锁的三个典型场景
- 【多线程】并发死锁问题与企业级解决方案
1. 死锁是什么?有什么危害 1.1 什么是死锁 发生在并发种 互不相让:当两个(或更多)线程(或进程)相互持有对方所需要的资源,又不主动释放,导致所有人都无法继续前进,导致程序陷入无尽的阻塞,这就是 ...
- Java 程序死锁问题原理及解决方案
原文出处: IBM developerWorks Java 语言通过 synchronized 关键字来保证原子性,这是因为每一个 Object 都有一个隐含的锁,这个也称作监视器对象.在进入 syn ...
- 线程死锁的成因?如何查找并定位死锁,解决死锁?这里教你几招~
目录 什么是死锁? 死锁代码案例: 出现死锁的原因 教你如何定位死锁位置~ 死锁解决方法 什么是死锁? 死锁就是指线程t1要使用的资源被线程t2占用,线程t2想使用的资源被线程 t1占用,这就像两股绳 ...
最新文章
- Tungsten Fabric SDN — 软件架构
- 【Java】判断字符串是否含字母
- BW事务代码SXMB_ADM、 SICF、SMICM简介
- Unix Shell 数学计算命令
- 光纤测试仪为什么使用单芯法为光纤损耗测量
- IE8 beta2现已正式发布!
- 龙族幻想服务器维护中怎么办,龙族幻想遇到无法连接服务器?两招教你轻松解决...
- velocity 时间显示 时间格式化 时间转化
- 进程queue和线程queue
- 台安变频器n2按键说明_台安变频器N2
- Android 查看是否支持指定解码器(H265)
- 吴伯凡-认知方法论-如何增加自己认知的维度
- kali linux怎么安装无线网卡驱动,Kali Linux 安装BCM43142网卡驱动
- Unity http协议连接封装简易版(已测试可用)
- 帝国CMS模板组创建和管理,让网站完成迅速”变脸“
- 【2.5万字】详解 Python-docx 自动生成word图文报告
- linux v4l2系统详解,Linux摄像头驱动学习之:(一)V4L2_框架分析
- x86架构下的安卓虚拟化
- 2.6.36.2 s3c6410 触摸屏驱动移植。
- [LeetCode]682. 棒球比赛(Baseball Game)Java
热门文章
- 多旋翼油门量与升力关系
- 兴趣变高薪副业,知名插画师走尺带你感受插画的魅力
- 提升学习 Prompt 总结
- Scala 继承和特质
- python标准数据类型叮叮叮
- 绘画入门经典教程——如果你想, 一切皆有可能!
- asp.net动态网页制作视频教程
- 如何培养员工的团队合作精神
- Payment:支付宝即时到账接口接入教程
- 关于const A* f(const A* pSrc,A* const pDst,int v=2,...) const throw();