Java线程死锁实例及解决方法

 更新时间:2019年11月22日 11:33:23   作者:最喜欢夏天了  
这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1、死锁的定义

所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进

2、死锁产生的必要条件

互斥条件:线程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个线程所占有。此时若有线程请求该资源,则请求线程只能等待。

不剥夺条件:线程所获得的资源在未使用完毕之前,不能被其他线程倾向夺走,即只能由获得该资源的线程自己来释放(只能是主动释放)。

请求和保持条件:线程已经保持了至少一个资源,但又提出了新的资源请求,而该线程已被其他线程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

循环等待条件:存在一种线程资源的循环等待链,链中每一个线程已获得的资源同时被链中下一个线程所请求。即存在一个处于等待状态的线程集合{P1,P2,...,Pn},其中Pi等待的资源被P(i+1)占有(i=0,1,..,n-1),Pn等待的资源被P0占有,如下图。

3、产生死锁的一个例子

/**
 * 一个简单的死锁类
 * 当DeadLock类的对象flag==1时(td1),先锁定o1,睡眠500ms
 * 而td1在睡眠的时候另一个flag==0的对象(td2)线程启动,先锁定o2,睡眠500ms
 * td1 睡眠结束后需要锁定 o2 才能继续执行,而此时 o2 已被 td2 锁定;
 * td2 睡眠结束后需要锁定 o1 才能继续执行,而此时 o1 已被 td1 锁定;
 * td1、td2 相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
 */
public class DeadLock implements Runnable {
  public int flag = 1;
  //静态对象是类的所有对象共享的
  private static Object o1 = new Object(), o2 = new Object();

  @Override
  public void run() {
    System.out.println("flag="+flag);
    if(flag==1){
      synchronized (o1){
        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        synchronized (o2){
          System.out.println("1");
        }
      }
    }
    if(flag==0){
      synchronized (o2){
        try {
          Thread.sleep(500);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        synchronized (o1){
          System.out.println("0");
        }
      }
    }
  }
  public static void main(String[] args) {
    DeadLock td1 = new DeadLock();
    DeadLock td2 = new DeadLock();
    td1.flag=1;
    td2.flag=0;
    //td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。
    //td2的run()可能在td1的run()之前运行
    new Thread(td1).start();
    new Thread(td2).start();
  }
}

4、如何避免死锁

在有些情况下死锁是可以避免的。两种用于避免死锁的技术

1)加锁顺序(线程按照一定的顺序加锁

2)加锁时限(线程获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • java中使用session监听实现同帐号登录限制、登录人数限制

    java中使用session监听实现同帐号登录限制、登录人数限制

    本文主要介绍了java中使用session监听实现同帐号登录限制、登录人数限制,通过session来监听在线人数和登陆限制,有需要的童鞋可以了解一下。
    2016-10-10
  • Spring Boot集成Java DSL的实现代码

    Spring Boot集成Java DSL的实现代码

    这篇文章主要介绍了Spring Boot集成Java DSL的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • Spring常用注解及http数据转换教程

    Spring常用注解及http数据转换教程

    这篇文章主要为大家介绍了Spring常用注解及http数据转换原理以及接收复杂嵌套对象参数与Http数据转换的原理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • 深入浅出Java mvc_动力节点Java学院整理

    深入浅出Java mvc_动力节点Java学院整理

    这篇文章主要为大家详细介绍了MVC的基础知识,MVC是一个框架模式,它强制性的使应用程序的输入、处理和输出分开,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • 判断以逗号分隔的字符串中是否包含某个数的实例

    判断以逗号分隔的字符串中是否包含某个数的实例

    下面小编就为大家带来一篇判断以逗号分隔的字符串中是否包含某个数的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • MyBatis获取参数值的两种方式详解

    MyBatis获取参数值的两种方式详解

    本文主要介绍了MyBatis获取参数值的两种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Java动态加载类示例详解

    Java动态加载类示例详解

    这篇文章主要给大家介绍了关于Java动态加载类的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Java函数习惯用法详解

    Java函数习惯用法详解

    本篇文章主要给大家总结了java中最常用的函数的用法和写法,需要的朋友参考一下吧。
    2017-12-12
  • Java 使用json-lib处理JSON详解及实例代码

    Java 使用json-lib处理JSON详解及实例代码

    这篇文章主要介绍了Java 使用json-lib处理JSON详解及实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • IDEA中使用jclasslib插件可视化方式查看类字节码的过程详解

    IDEA中使用jclasslib插件可视化方式查看类字节码的过程详解

    查看JAVA字节码有两种方式一种是使用 jdk命令 javap,还有一种就是 使用 插件了,今天给大家分享IDEA中使用jclasslib插件可视化方式查看类字节码的过程详解,感兴趣的朋友跟随小编一起看看吧
    2021-05-05

最新评论