Java死锁
来源:互联网 发布:网络pos支付平台 编辑:程序博客网 时间:2024/06/05 15:24
什么是死锁
死锁:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期的阻塞,因此程序不可能正常终止。(两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。)
死锁的产生条件
- 互斥使用:即当资源被一个线程占用(使用)时,别的线程不能使用。
- 不可抢占:资源请求者不能强制从资源占有者手中抢夺资源,资源只能等待占有者主动释放。
- 请求和保持:即当资源请求者在请求其他资源的同时保持对原有资源的占有。
- 循环等待:存在一个等待队列,P1占有p2的资源,p2占有p3的资源,p3占有p1的资源。就这样形成了一个等待环路。
打个比方用来帮助理解:
程序猿:cxy1 , 程序猿:cxy2 , 程序猿:cxy3
程序媛:cxyX , 程序媛:cxyY , 程序媛:cxyZ
1. 互斥使用:当程序猿占用一个程序媛时,别的程序猿不能再去占用这个程序媛。
2. 不可抢占:不能挖墙脚。
3. 请求和保持:当一个程序猿在占用一个程序媛时,还可以向另一个程序媛表白(请求)。
4. 循环等待:cxy1喜欢cxyX却占用cxy2喜欢的cxyY,cxy2占用着cxy3喜欢的cxyZ,cxy3占用着cxy1喜欢的cxyX,他们都在等待对方放手。
当上述四个条件都成立时,则形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
死锁的Java实例:
public class DeadLock { public static String obj1 = "obj1"; public static String obj2 = "obj2"; public static void main(String[] args) { LockA lockA = new LockA(); new Thread(lockA).start(); LockB lockB = new LockB(); new Thread(lockB).start(); } static class LockA implements Runnable { public void run() { try { System.out.println(new Date().toString() + " : LockA 开始执行"); while (true) { synchronized (obj1) { System.out.println(new Date().toString() + " : LockA 锁住了obj1"); Thread.sleep(3000);// 获取obj1后先等一会儿,让LockA有足够的时间锁住obj2 synchronized (obj2) { System.out.println(new Date().toString() + " : LockA 锁住了obj2"); Thread.sleep(60 * 1000);// 为测试,占用了就不放 } } } } catch (InterruptedException e) { e.printStackTrace(); } } } static class LockB implements Runnable { public void run() { try { System.out.println(new Date().toString() + " : LockB 开始执行"); while (true) { synchronized (obj2) { System.out.println(new Date().toString() + " : LockB 锁住了obj2"); Thread.sleep(3000);// 获取obj2后先等一会儿,让LockB有足够的时间锁住obj1 synchronized (obj1) { System.out.println(new Date().toString() + " : LockB 锁住了obj1"); Thread.sleep(60 * 1000);// 为测试,占用了就不放 } } } } catch (InterruptedException e) { e.printStackTrace(); } } }}//结果打印Wed Nov 01 17:38:00 CST 2017 : LockB 开始执行Wed Nov 01 17:38:00 CST 2017 : LockB 锁住了obj2Wed Nov 01 17:38:00 CST 2017 : LockA 开始执行Wed Nov 01 17:38:00 CST 2017 : LockA 锁住了obj1
信号量(解决死锁)
为了解决这个问题,我们不使用显示的去锁,我们用信号量去控制。
信号量可以控制资源能被多少线程访问,这里我们指定只能被一个线程访问,就做到了类似锁住。而信号量可以指定去获取的超时时间,我们可以根据这个超时时间,去做一个额外处理。
对于无法成功获取的情况,一般就是重复尝试,或指定尝试的次数,也可以马上退出。
详细解决方案参考:Java死锁和解决方式
阅读全文
0 0
- java死锁,避免死锁
- Java.死锁
- Java死锁
- java死锁
- java ----死锁
- Java死锁
- java 死锁
- Java - 死锁
- java 死锁
- JAVA 死锁
- java死锁
- java死锁
- Java死锁
- Java - 死锁
- Java 死锁
- java 死锁
- java死锁
- Java死锁
- Java面试题整理
- Xilinx FPGA常见配置模式总结
- C++ 对象
- 怎样才能赚到钱系列(三)
- 6-1 Two Stacks In One Array-PTA双指指针stack表操作实现
- Java死锁
- C#简单Socket
- Spring代理模式
- 重定向理解
- 常用排序算法总结
- Android Studio编译项目的时候报Manifest merger failed
- Nutch 深入浅出
- css尺寸单位
- 网页视频播放的常见兼容方式总结