java中死锁_关于java中死锁的总结
关于死锁,估计很多程序员都碰到过,并且有时候这种情况出现之后的问题也不是非常好排查,下面整理的就是自己对死锁的认识,以及通过一个简单的例子来来接死锁的发生,自己是做python开发的,但是对于死锁的理解一直是一种模糊的概念,也是想过这次的整理更加清晰的认识这个概念。
用来理解的例子是一个简单的生产者和消费者模型,这里是有一个生产者,有两个消费者,并且注意代码中使用notify方法的代码行
packagestudy_java.ex11;importjava.util.LinkedList;importjava.util.List;public classPCDemo1 {public static voidmain(String[] args){
Pool pool= newPool();
Producter p1= newProducter(pool);
p1.setName("p1");
Consumer c1= newConsumer(pool);
Consumer c2= newConsumer(pool);
c1.setName("c1");
c2.setName("c2");
p1.start();
c1.start();
c2.start();
}
}classPool{private List list = new LinkedList();private int Max = 1;public void addLast(intn){
String name=Thread.currentThread().getName();synchronized (this){while (list.size() >=Max){try{
System.out.println(name+".wait()");this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println(name+ "+" +n);
list.add(newInteger(n));
System.out.println(name+ ".notify()");this.notify(); //注意这里是调用的是notify方法
}
}public intremove(){
String name=Thread.currentThread().getName();synchronized (this){while (list.size() == 0){try{
System.out.println(name+ ".wait()");this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println(name+ "-" + 0);int no = list.remove(0);
System.out.println(name+ ".notify()");this.notify(); //注意这里是调用的是notify方法
returnno;
}
}
}//生产者
class Producter extendsThread{privatePool pool;static int i = 1;publicProducter(Pool pool){this.pool =pool;
}public voidrun(){while (true){
pool.addLast(i++);
System.out.println("生产者生产了"+i+"号");
}
}
}//消费者
class Consumer extendsThread{privatePool pool;publicConsumer(Pool pool){this.pool =pool;
}public voidrun(){while (true){int no =pool.remove();
System.out.println("消费者消费了"+no+"号");
}
}
}
这段代码的运行效果是日志,在最后程序卡主不动了:
c1.wait()
p1+1p1.notify()
c1-0c1.notify()
消费者消费了1号
c1.wait()
生产者生产了2号
p1+2p1.notify()
c1-0c1.notify()
消费者消费了2号
c1.wait()
生产者生产了3号
p1+3p1.notify()
c1-0c1.notify()
消费者消费了3号
c1.wait()
生产者生产了4号
p1+4p1.notify()
c1-0c1.notify()
消费者消费了4号
c1.wait()
生产者生产了5号
p1+5p1.notify()
c1-0c1.notify()
消费者消费了5号
c1.wait()
生产者生产了6号
p1+6p1.notify()
生产者生产了7号
c1-0c1.notify()
消费者消费了6号
c1.wait()
p1+7p1.notify()
生产者生产了8号
p1.wait()
c2-0c2.notify()
消费者消费了7号
c2.wait()
c1.wait()
p1+8p1.notify()
生产者生产了9号
p1.wait()
c2-0c2.notify()
消费者消费了8号
c2.wait()
c1.wait()
对上面的出现卡主的情况进行分析,理解为啥会卡主:
从这次的执行效果可以看出第一次是c1抢到了执行权,但是这个时候pool是空
所以c1没有可以消费的对象,被放入到了等待队列
接着p1抢到了执行权,生产了1个,然后p1.notify(),这个时候等待队列里只有c1,所以c1被唤醒,c1消费了1个,然后c1.notify(), 这个时候等待队列也没有等待的,这个时候有被c1抢到了执行权,但是pool里没有可以消费的内容,所以c1.wait() 进入到等待队列
这个时候p1抢到执行权,生产了1个,然后p1.notify(),这个时候等待队列里只有c1,所以c1被唤醒,c1也抢到了执行权,消费了1个,然后c1.notify()
同样这个时候等待队列里没有等待的,c1这次又抢到了执行权,但pool里没有可以消费的内容,所以c1.wait(),进入到等待队列
p1 又抢到了执行权,生产1个,然后p1.notify(),这个时候等待队列里只有c1,所以c1被唤醒,c1也抢到了执行权,消费了1个,然后c1.notify()
同样这个时候等待队列里没有等待的,c1这次又抢到了执行权,但pool里没有可以消费的内容,所以c1.wait(),进入到等待队列
.......这种情况重复了几次
但是运行到下面这段的时候问题出现了:
p1+7p1.notify()
生产者生产了8号
p1.wait()
c2-0c2.notify()
消费者消费了7号
c2.wait()
c1.wait()
p1+8p1.notify()
生产者生产了9号
p1.wait()
c2-0c2.notify()
消费者消费了8号
c2.wait()
c1.wait()
继续进行分析,中间重复的部分不做分析了,和前面的过程是一样的
这个时候等待队里里依然是c1 这个时候p1抢到了执行权,生产了1个,p1.notify() 这个时候等待队列里只有c1,所以c1被唤醒,但是c1没有抢过p1,p1自己又抢到了执行权,但是这个时候pool里面已经有内容,所以p1没有生产,p1.wait(),p1进入等待队列
这个时候c2抢到了执行权,c2消费1个,c2.notify() 这个时候等待队里是p1,p1被唤醒,但是这个时候c2抢到了执行权,但是pool没有内容可以消费所以c2.wait() 进入等待队列
接着c1抢到了执行权,同样pool没有可以消费的内容,c1.wait() 进入到等待队列
p1这个时候抢到了执行权,p1生产了1个,接着p1.notify() 这个时候等待队列里有c1和c2,但是只有一个会被唤醒,不管是哪个,结果没抢过p1,p1再次拿到执行权,但是这个时候pool已经有内容,所以p1.wait() p1进入等待队列
从下面是c2执行,可以看出刚才是c2被唤醒了,这个时候c2也拿到了执行权消费了1个。c2.notify() 等待队列里这个时候有c1 和p1 但是这个时候c2 自己抢到了执行权,但是没有可以消费的,c2.wait() c2 进入等待队列
不巧的是刚才抢到执行权的正好是c1,所以c1继续wait,再次进入等待队列
到这个时候p1 c1 c2 都进入等待队列里,都在等待唤醒,也就出现了程勋最后卡住不动的情况
解决的方法有两种:
第一种:
其实解决上面的方法也比较简单,就是把调用notify的地方全部换成notifyAll方法
notify和notifyAll的区别是,当执行notifyAll的时候会唤醒所有等待的线程,从而避免之前的都在等待队列等待的问题
第二种:
就是wait()的时候加上超时参数,不是像之前一直傻等,而是在超过既定的时间之后自己唤醒
java中死锁_关于java中死锁的总结相关推荐
- java多线程同步与死锁_浅析Java多线程中的同步和死锁
Value Engineering 1基于Java的多线程 多线程是实现并发机制的一种有效手段,它允许编程语言在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立,且与进程一样拥有独立 ...
- java jstack 死锁_利用jstack检测死锁DeadLock
首先,制造一个死锁程序如下: public class testJstack { final static Object obj_1 = new Object(); final static Obje ...
- java jstack 死锁_用jstack找死锁
java死锁主要依靠jstack命令来查找. 检测jstack 先配置好jdk环境变量,打开一个终端命令行,输入jstack回车.如果看到如下的字样,说明jstack是可用的. Usage: jsta ...
- java coin介绍_代码示例中的Java 7:Project Coin
java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...
- java final 类_在Java中,final修饰的类有什么特点
展开全部 关于Java中的32313133353236313431303231363533e4b893e5b19e31333264663736final(2010-09-09 14:19:48)转载▼ ...
- java arraylist 函数_使用Java-8中的函数ArrayList
问题描述: 我希望能够使用从另一个类传入的函数的ArrayList(其中函数已在其他类中定义).如果在一个类中定义了可能具有不同输入和返回类型的函数列表,我希望能够将其中一些的ArrayList(可能 ...
- java logging包_用JDK中提供的java.util.logging.*包创建Logger对象----原创
由于项目中用到了Applet与Servlet之间(客户端用Applet.Server端用Servlet)的通信,要求: 1:>客户端与服务端必须出Log. 2:>浏览器在加载Applet时 ...
- android studio插入数据表中没有_学Java能拿高薪吗 Java中常见排序算法有哪些
学Java能拿高薪吗?Java中常见排序算法有哪些?作为老牌编程语言,Java拥有广阔的市场占有率,几乎90%以上的大中型互联网应用系统在服务端开发都会首选Java.为了加入到Java这一高薪行业,很 ...
- java jar 目录_将Java类路径中的所有jar包括在一个目录中
有没有一种方法可以将所有的jar文件包含在类路径的目录中? 我正在尝试java -classpath lib / *.jar :. my.package.Program,它无法找到当然在这些罐子里的类 ...
- java gradle构建_在Gradle中为JPMS构建Java 6-8库
java gradle构建 通过提供Java 9 module-info.class了解如何使用Gradle构建支持JPMS( Java平台模块系统 )的Java 6-8库. 介绍 如果您需要JPMS ...
最新文章
- 鸟哥的Linux私房菜10.16 vim程序编辑器
- Java继承时构造函数的关系
- 【数据结构与算法】之面试必考的“二分算法”系统梳理
- 41.django中auth用户认证
- web测试点和app测试点
- android sqlite多条件查询,sqlite 多条件查询
- php随浏览器大小变化,如何在将图像显示到浏览器之前使用php重新调整图像大小?...
- 基于SQL求集合的交、并、补
- word文档怎么删除多余的空白页?
- ListView和条目点击事件、条目长按事件
- xp win7 绿色chrome
- Kali网络渗透测试二——网络嗅探与身份认证
- 我的软件推广成功之路 [转]
- Beta产品测试报告:那周余嘉熊掌将得队、为了交项目干杯队
- Windows server 2012R2或Windows 8.1如何成功离线安装.net 4.7
- 笔记:刘未鹏思考的技术与艺术(原“学会思考”)
- 做好公司网站建设方案的关键在于这些方面
- 回首来路漫漫,矢志不改初心
- linux磁盘分区fdisk命令详解及云硬盘挂载实操
- 分组密码的设计思想、概述、含义
热门文章
- Flink 零基础实战教程:如何计算实时热门商品
- 三问(why?what?how?)金融领域的机器学习
- 双十一丝般顺滑体验背后:阿里云洛神网络虚拟化系统揭秘
- 火山引擎进军云市场,计划未来三年服务十万客户
- Kubernetes 也有局限性吗?
- 腾讯智慧交通战略重磅升级 打造以人为中心的未来交通
- MQ 技术产品井喷,今天来详聊一下腾讯开源消息中间件 TubeMQ | 原力计划
- 国庆出游,这个银行卡大小的充电宝一定要带
- Kafka精华问答 | Kafka的主要应用场景有哪些?​
- python 下载图片到内存卡_python - 获取图像大小而不将图像加载到内存中