java实现死锁的示例代码

作者:土豆Z120553 时间:2023-10-12 18:12:40 

什么是死锁

我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由桥的两端驶上该桥,则对于A车来说,它走过桥面左面的一段路(即占有了桥的一部分资源),要想过桥还须等待B车让出右边的桥面,此时A车不能前进;对于B车来说,它走过桥面右边的一段路(即占有了桥的一部分资源),要想过桥还须等待A车让出左边的桥面,此时B车也不能前进。两边的车都不倒车,结果造成互相等待对方让出桥面,但是谁也不让路,就会无休止地等下去。这种现象就是死锁。如果把汽车比做进程,桥面作为资源,那麽上述问题就描述为:进程A占有资源R1,等待进程B占有的资源Rr;进程B占有资源Rr,等待进程A占有的资源R1。而且资源R1和Rr只允许一个进程占用,即:不允许两个进程同时占用。结果,两个进程都不能继续执行,若不采取其它措施,这种循环等待状况会无限期持续下去,就发生了进程死锁。

在计算机系统中,涉及软件,硬件资源都可能发生死锁。例如:系统中只有一台CD-ROM驱动器和一台打印机,某一个进程占有了CD-ROM驱动器,又申请打印机;另一进程占有了打印机,还申请CD-ROM。结果,两个进程都被阻塞,永远也不能自行解除。

所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。很显然,如果没有外力的作用,那麽死锁涉及到的各个进程都将永远处于封锁状态。从上面的例子可以看出,计算机系统产生死锁的根本原因就是资源有限且操作不当。即:一种原因是系统提供的资源太少了,远不能满足并发进程对资源的需求。这种竞争资源引起的死锁是我们要讨论的核心。例如:消息是一种临时性资源。某一时刻,进程A等待进程B发来的消息,进程B等待进程C发来的消息,而进程C又等待进程A发来的消息。消息未到,A,B,C三个进程均无法向前推进,也会发生进程通信上的死锁。另一种原因是由于进程推进顺序不合适引发的死锁。资源少也未必一定产生死锁。就如同两个人过独木桥,如果两个人都要先过,在独木桥上僵持不肯后退,必然会应竞争资源产生死锁;但是,如果两个人上桥前先看一看有无对方的人在桥上,当无对方的人在桥上时自己才上桥,那麽问题就解决了。所以,如果程序设计得不合理,造成进程推进的顺序不当,也会出现死锁。

死锁

只有当t1线程占用o1且正好也需要o2,t2此时占用o2且正好也需要o1的时候才会出现死锁,(类似于2个人拿着两个筷子吃饭,都是需要对方的一根筷子才能吃)

以下代码t1线程占用o1,并且获取到o2对象后才会释放o1,而t2线程先占用o2又去获取o1,而此时的o1被t1线程占用,o2被t2线程占用,t1和t2都在无限等待,就会出现死锁。


package javasimple;
/**
* 死锁demo
* @author haokui
*
*/
public class DieSynchronized {
public static void main(String[] args) {
 /**
  * 创建并启动两个线程t1、t2。两个线程都要共享o1、o2两个对象
  */
 Object o1 = new Object();
 Object o2 = new Object();
 Thread t1 = new Thread(new T1(o1,o2));
 Thread t2 = new Thread(new T2(o1,o2));
 t1.start();
 t2.start();
}
}
//创建两个线程类
class T1 implements Runnable {
Object o1;
Object o2;
public T1(Object o1, Object o2){
 this.o1 = o1;
 this.o2 = o2;
}
public void run() {
 //锁o1和o2
 synchronized (o1) {
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  synchronized (o2) {
   System.out.println("o2");
  }
 }
}
}
class T2 implements Runnable {
Object o1;
Object o2;
public T2(Object o1, Object o2){
 this.o1 = o1;
 this.o2 = o2;
}
public void run() {
 synchronized (o2) {
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  synchronized (o1) {
   System.out.println("o1");
  }
 }

}
}

注意:只有o1和o2被共享的时候才会出现并发的情况,可通过构造函数的方式共享两个对象。

来源:http://www.cnblogs.com/hkdpp/p/8341288.html

标签:java,死锁
0
投稿

猜你喜欢

  • Java中 ? extends T 和 ? super T的理解

    2022-06-26 19:50:23
  • springboot自动配置原理以及spring.factories文件的作用详解

    2021-12-20 20:19:27
  • Unity查找游戏物体的六种方式详解

    2021-07-09 18:23:17
  • 利用thrift实现js与C#通讯的实例代码

    2022-09-07 15:49:13
  • C#通过属性名称获取(读取)属性值的方法

    2023-10-10 11:49:06
  • java 二叉查找树实例代码

    2022-07-23 22:54:28
  • Android Drawable代码编写的新姿势分享

    2021-11-21 04:11:12
  • android RecyclerView的一些优化点介绍

    2021-08-21 06:27:08
  • Java并发编程系列之LockSupport的用法

    2022-04-07 06:48:58
  • Java超全面梳理内部类的使用

    2021-09-06 11:24:07
  • 基于C#实现手机号码归属地接口调用

    2022-07-14 09:46:54
  • Android自定义ViewGroup多行多列效果

    2022-10-31 06:07:17
  • Java全面细致讲解Cookie与Session及kaptcha验证码的使用

    2021-09-03 23:10:56
  • 设置JavaScript自动提示-Eclipse/MyEclipse

    2022-06-15 12:41:05
  • Kotlin协程之Flow异常示例处理

    2022-10-02 09:30:58
  • Java详细分析LCN框架分布式事务

    2022-10-17 15:49:08
  • c#中XML解析文件出错解决方法

    2022-01-21 00:38:50
  • C# 通过NI-VISA操作Tektronix TBS 2000B系列示波器的实现步骤

    2023-11-02 01:44:38
  • springboot docker jenkins 自动化部署并上传镜像的步骤详解

    2023-07-28 01:54:38
  • springboot中自定义异常以及定制异常界面实现过程解析

    2023-05-13 09:14:00
  • asp之家 软件编程 m.aspxhome.com