一、什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无限等待。

二、产生死锁的原因与四个条件

2.1 死锁原因

竞争资源

  多个线程竞争同一个不可剥夺的系统资源,或者多个线程竞争同一个临时资源(包括缓存、信号、消息、对象数据等)

  补充:系统资源分为两类:可剥夺资源(CPU、主存等),不可剥夺资源(打印机、声卡等等输出设备)

推进顺序不合理(获取锁的顺序不合理)

  程序运行的顺序不合理,进程一获取资源A后,此时进程二获取资源B,然后进程一想获取资源B,进程二想获取资源A;这两个进程互相不释放资源,就会死锁

2.2 四个条件

  • 互斥:同一资源在同一时间只能被同一进程使用
  • 请求与保持:进程在拥有一个资源时,坚决保持此资源,并且一直去请求另外的新资源
  • 不可剥夺:进程已经拥有的资源在未使用完之前,不可以被剥夺,只能在使用完被释放,也可说唯一占有
  • 环路等待:进程一直等待新资源,产生了环形链

三、死锁案例

public class DeadLock {
public static void main(String[] args) {
ArrayList<String> listA = new ArrayList<>();
ArrayList<String> listB = new ArrayList<>();
final Object A = new Object();
final Object B = new Object();

new Thread(() -> {
synchronized (listA) {
System.out.println("线程一获取到对象A的锁");
listA.add("A");
try {
Thread.sleep(500);
synchronized (listB) {
System.out.println("线程一获取到对象B的锁");
}
} catch (InternalError | InterruptedException e) {
e.printStackTrace();
}
}
}).start();

new Thread(() -> {
synchronized (listB) {
System.out.println("线程二获取到对象B的锁");
listB.add("B");
try {
Thread.sleep(500);
synchronized (listA) {
System.out.println("线程二获取到对象A的锁");
}
} catch (InternalError | InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}

运行后就可以发现,线程一、二会一直等待对方锁持有的锁

四、防止死锁的方法

破坏死锁四个条件中的一个就可以防止死锁

  • 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
  • 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
  • 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
  • 资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)

具体应用方法(说人话)

(1) 确定锁的顺序,并且整个应用中都按照这个顺序来获取锁。

例如:我们上面的 Demo 中,两个线程获取锁的顺序都为 先获取对象 a 的锁,在获取对象 b 的锁,就不会出现死锁的问题。

(2) 超时放弃

  当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去。此时我们一般需要避免嵌套锁

  然而我们可以用其它的锁:

  • Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。
  • 采用分布式锁,加上锁的时限,那么锁就不会无限等待了

java的死锁与解决方法的更多相关文章

  1. Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法

    Tomcat 优化 java.lang.OutOfMemoryError: Java heap space 的解决方法 java.lang.OutOfMemoryError: Java heap sp ...

  2. java.lang.ClassNotFoundException的解决方法

    java.lang.ClassNotFoundException的解决方法   出现这个问题的原因可能很多,但是最终原因都是部署的项目文件中没有这个类包. 那么出错的点在哪呢?逐一排除! 1.首先在项 ...

  3. SqlServer表死锁的解决方法

    SqlServer表死锁的解决方法   前些天写一个存储过程,存储过程中使用了事务,后来我把一些代码注释掉来进行调试找错,突然发现一张表被锁住了,原来是创建事务的代码忘记注释掉.本文表锁住了的解决方法 ...

  4. Tomcat部署java项目java.lang.OutOfMemoryError异常解决方法

    java.lang.OutOfMemoryError异常解决方法 Window系统环境下,在catalina.bat文件第一行添加以下内容 set JAVA_OPTS=-Xms512m -Xmx512 ...

  5. 对于jfinal中java.lang.Long cannot be cast to java.lang.Integer的解决方法

    @Jfinal 老大提供的解决方法 当数据库字段为 int 型(有符号int型),但是如果在 sql 中使用了某些函数,jdbc 会自动转型为 long,例如:select sum(money) fr ...

  6. android 工程里缺少 R.java 文件原因和解决方法

    作为新手,学习android 的时候难免要导入一些示例,目的为了更加了解android各种API用法,顺便也可以学习下别人代码的写法. 可是导入android源码后,基本都有错误,R.java也不会自 ...

  7. Java中线程出现Exception in thread "Thread-0" java.lang.IllegalMonitorStateException异常 解决方法

    代码 package thread; public class TestChongNeng { public static void main(String[] args) { Thread t1 = ...

  8. Java线程死锁查看分析方法

    如何查看是否有Java线程死锁?下面介绍两种方法. 一.Jconsole        Jconsole是JDK自带的图形化界面工具,使用JDK给我们的的工具JConsole,可以通过打开cmd然后输 ...

  9. (转)Android工程出现 java.lang.NoClassDefFoundError错误解决方法

    在Eclipse中,导入Android工程,工程没有报错,运行时,出现 java.lang.NoClassDefFoundError类没有找到的错误.从问题上可以看出是导入包出错的原因.遂百度加谷歌. ...

  10. Java小问题的解决方法系列

    1)IDEA中文乱码,解决方法:http://blog.csdn.net/zht666/article/details/8953516 2)卸载OpenJdk,http://my.oschina.ne ...

随机推荐

  1. 765. 情侣牵手 (Hard)

    问题描述 765. 情侣牵手 (Hard) n 对情侣坐在连续排列的 2n 个座位上,想要牵到对方的手. 人和座位由一个整数数组 row 表示,其中 row[i] 是坐在第 i 个座位上的人的 ID. ...

  2. Python 集合常用方法

    数据类型:int/str/bool/list/dict/tuple/float/set   (set类型天生去重) 一.集合的定义 s = set()  #定义空集合 s = {'a','b','c' ...

  3. Python 获取IP地址

    import socket def get_host_ip(): """ 查询本机ip地址 :return: """ try: s=sock ...

  4. oracle常用知识随笔

    1.创建表空间及用户赋权 create tablespace spaceone datafile '/dev/spaceone'size 80mextent management localsegme ...

  5. Linux服务器时间校准

    当发现系统时间不正确时可以通过 date 命令查看Linux系统的当前时间 最简便的修改方法,我们可以通过 date -s "20190917 22:04:00" 来直接修改Lin ...

  6. 替代学习物联网-云服务-04TLINK云MQTT

    1.注册TLINK www.tlink.io 记录下登录的用户名,密码.MQTT需要 2.添加设备  3.设备序列号:clientID 4.mqtt.fx调试器  5.订阅主题 在MQTT.fx上,单 ...

  7. 如何在超星下载非资料页面的ppt

    首先打开迅雷(没有就复制到网页下载) 点击f12 点击网络,筛查出输入flag,在响应模块中找到ppt,复制网址并下载

  8. FPGAUSB控制器编程

    FPGA产生PLL LED子module,显示FPGA在运行 USB控制子module,USB时钟输入,状态输入,总线输出,USBFIFO地址总线,数据双向总线. USB状态机,Flaga有效时,转为 ...

  9. AJAX-动力节点

    AJAX(Asynchronous Javascript And Xml) 传统请求及缺点 传统的请求都有哪些? 直接在浏览器地址栏上输入URL. 点击超链接 提交form表单 使用JS代码发送请求 ...

  10. HTML初体验之各种标签练习

    HTML初体验之各种标签练习 首先是<!DOCTYPE>标签 放在网页顶部的doctype声明是让浏览器进入正确呈现模式的关键.浏览器自动切换到恰当的呈现模式,以便正确显示由doctype ...