JAVA中死锁例子分析和上下文切换的实战
来源:互联网 发布:2016中国中小企业数据 编辑:程序博客网 时间:2024/05/22 03:37
本篇是整理《java多线程编程核心技术》和《java并发编程的艺术》中对于死锁和上下文切换的查看命令的总结。
一、死锁
1.死锁的图解
- 死锁
死锁是两个甚至多个线程被永久阻塞时的一种运行局面。死锁的原因:由于两个甚至多个线程相互等待对方已被锁定的资源。
2.死锁的例子
public class DeadThreadLockTest implements Runnable{ private Object lock1 = new Object(); private Object lock2 = new Object(); private String name; public void setFlag(String name){ this.name = name; } public static void main(String[] args) throws InterruptedException { DeadThreadLockTest dtlt = new DeadThreadLockTest(); dtlt.setFlag("a"); Thread t1 = new Thread(dtlt,"t1"); t1.start(); Thread.sleep(1000); dtlt.setFlag("b"); Thread t2 = new Thread(dtlt,"t2"); t2.start(); } @Override public void run() { if(name.equals("a")) { synchronized (lock1){ System.out.println("name : " + name + " -- " + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2){ System.out.println("lock1 ---> lock2"); } } } if (name.equals("b")){ synchronized (lock2){ System.out.println("name : " + name + " -- " + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1){ System.out.println("lock2 ---> lock1"); } } } }}
ide一直处于run状态,运行控制台打印的结果:
#org.dufy.cha2.t2.DeadThreadLockTestname : a -- t1name : b -- t2
3.检查线程状态命令-查看是否发生死锁
(1):jps命令:显示当前所有的java进程(显示当前用户的所有java进程的PID)
F:\My_WorkSpace\idea_project>jps1684 RemoteMavenServer11088 Jps2816 AppMain #我们上面代码的执行线程id12602332 Launcher
(2):jstack :当前线程的状态
F:\My_WorkSpace\idea_project>jstack -l 28162017-10-04 11:02:26Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):"DestroyJavaVM" prio=6 tid=0x000000000173e000 nid=0x1820 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None"t2" prio=6 tid=0x000000000dd3c800 nid=0x22d0 waiting for monitor entry [0x000000000e92f000] java.lang.Thread.State: BLOCKED (on object monitor) at org.dufy.cha2.t2.DeadThreadLockTest.run(DeadThreadLockTest.java:71) - waiting to lock <0x00000007d61fc418> (a java.lang.Object) - locked <0x00000007d61fc428> (a java.lang.Object) at java.lang.Thread.run(Thread.java:745) Locked ownable synchronizers: - None"t1" prio=6 tid=0x000000000dd3b800 nid=0x9d8 waiting for monitor entry [0x000000000e82f000] java.lang.Thread.State: BLOCKED (on object monitor) at org.dufy.cha2.t2.DeadThreadLockTest.run(DeadThreadLockTest.java:54) - waiting to lock <0x00000007d61fc428> (a java.lang.Object) - locked <0x00000007d61fc418> (a java.lang.Object) at java.lang.Thread.run(Thread.java:745) Locked ownable synchronizers: - None"Finalizer" daemon prio=8 tid=0x000000000bc5f800 nid=0x268c in Object.wait() [0x000000000dc2f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000007d6084858> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) - locked <0x00000007d6084858> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) Locked ownable synchronizers: - None"Reference Handler" daemon prio=10 tid=0x000000000bc59000 nid=0x2054 in Object.wait() [0x000000000db2f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000007d6084470> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:503) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133) - locked <0x00000007d6084470> (a java.lang.ref.Reference$Lock) Locked ownable synchronizers: - NoneFound one Java-level deadlock:============================="t2": waiting to lock monitor 0x000000000bc5f438 (object 0x00000007d61fc418, a java.lang.Object), which is held by "t1""t1": waiting to lock monitor 0x000000000bc5e0f8 (object 0x00000007d61fc428, a java.lang.Object), which is held by "t2"Java stack information for the threads listed above:==================================================="t2": at org.dufy.cha2.t2.DeadThreadLockTest.run(DeadThreadLockTest.java:71) - waiting to lock <0x00000007d61fc418> (a java.lang.Object) - locked <0x00000007d61fc428> (a java.lang.Object) at java.lang.Thread.run(Thread.java:745)"t1": at org.dufy.cha2.t2.DeadThreadLockTest.run(DeadThreadLockTest.java:54) - waiting to lock <0x00000007d61fc428> (a java.lang.Object) - locked <0x00000007d61fc418> (a java.lang.Object) at java.lang.Thread.run(Thread.java:745)Found 1 deadlock.
查看线程的状态,并发现Found one Java-level deadlock:,Found 1 deadlock.可以知道线程发生了死锁!
4.总结
死锁发生的条件
互斥条件:线程对资源的访问是排他性的,如果一个线程对占用了某资源,那么其他线程必须处于等待状态,直到资源被释放。
请求和保持条件:线程T1至少已经保持了一个资源R1占用,但又提出对另一个资源R2请求,而此时,资源R2被其他线程T2占用,于是该线程T1也必须等待,但又对自己保持的资源R1不释放。
不剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程剥夺,只能在使用完以后由自己释放。
环路等待条件:在死锁发生时,必然存在一个“进程-资源环形链”,即:{p0,p1,p2,…pn},进程p0(或线程)等待p1占用的资源,p1等待p2占用的资源,pn等待p0占用的资源。(最直观的理解是,p0等待p1占用的资源,而p1而在等待p0占用的资源,于是两个进程就相互等待)避免死锁
避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。
只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。
避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。
并发编程艺术:
(1)避免一个线程同时获取多个锁;
(2)避免一个线程在锁内同时占用多个资源,尽量保证每个锁占用一个资源;
(3)尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制;
(4)对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。
更多的相关死锁的资可以点击查看 : 死锁 - ImportNew
二、上下文切换
第一步:使用jps查询当前用户的线程
jps #命令
第二步:使用jstack命令dump线程信息
通过使用jstack查看当前pid的进程中的线程都在做什么。
#jstack 端口 > 重定向输出到dump目录下jstack 5899 > dump/dump5899
第三步:统计所有线程处于什么状态
通过命令统计当前pid进程中线程的状态。
grep java.lang.Thread.State dump/dump5899 | awk '{print $2$3$4$5}' | sort | uniq -c#--------------- 6 RUNNABLE 1 TIMED_WAITING(onobjectmonitor) 2 TIMED_WAITING(sleeping) 2 WAITING(onobjectmonitor) 1 WAITING(parking)
备注:
RUNNABLE:线程start()后,得到cup的时间片,执行状态;
TIMED_WAITING: sleep()方法执行后的状态;
BLOCKED : 出现在一个线程等待锁的时候;
WAITING: 线程执行了Object.wati方法后的状态;
第四步:打开dump文件查看对应状态的线程在做什么
打开dump文件,如果大量的线程处于BLOCKED 状态,查看处于BLOCKED 状态的线程在做什么,是什么原因导致线程大量处于BLOCKED 状态。
查看 WAITING 状态,为什么线程处于WAITING状态,是不是线程池中的启动线程太多,很多没有被用到。合理的设置线程池等。
第五步:找到原因,调整重试
发现有问题的线程状态,进行调整,然后重启相关服务,验证调整的结果。
如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!
欢迎访问我的csdn博客,我们一同成长!
“不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!”
博客首页:http://blog.csdn.net/u010648555
- JAVA中死锁例子分析和上下文切换的实战
- 分析和解决JAVA 内存泄露的实战例子
- 分析和解决JAVA 内存泄露的实战例子
- java中线程的同步和死锁案例分析
- java死锁的例子
- Java 死锁的例子
- Java死锁的例子
- 减少上下文切换实战
- Java多线程的上下文切换
- js 中call和apply的理解-切换上下文环境
- 中断的上下文切换和任务调度的上下文切换
- 线程上下文切换和进程上下文切换的区别
- 线程上下文切换和进程上下文切换的区别
- 线程上下文切换和进程上下文切换的区别
- 线程上下文切换和进程上下文切换的区别
- 线程上下文切换和进程上下文切换的区别
- suspend造成死锁的例子和原因分析
- Java同步和死锁的实例分析
- Ubuntu16.04 常用软件集锦[超实惠]
- 【GarsiaWachs算法】bzoj3229: [Sdoi2008]石子合并
- 如何准备阿里的社招
- leetcode题解之Isomorphic Strings
- 中科院谭铁牛爱徒研发出《碟中谍5》中的步态识别技术,不看脸50米内在人群中认出你
- JAVA中死锁例子分析和上下文切换的实战
- 搞科研的人,有什么不一样
- Angular Material Dialog 组件
- HDU
- Ubuntu 下Sublime安装配置及搭建轻量级C/C++IDE
- Jzoj3907 蜀传之单刀赴会(梦回三国系列)
- js 给textarea输入框内容自动添加换行符
- 【Java集合类】常见用法
- Appium怎样驱动手机Chrome浏览器