一、什么是死锁?

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

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

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. lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: meta line 4 and head, line 6, column 12 报错分析与解决方案

    报错分析: 我们检查代码没有任何问题,但报错显示:开始和结束标记不匹配. html:因为html是超文本标记语言,代码不规范也能解析. python:python是编程语言,代码不规范则解析不了. 解 ...

  2. nginx的301与302跳转详细配置教程

    什么是301跳转 301跳转也叫301重定向,也叫301转向,也叫301永久重定向,是网站建设过程中的一个功能.一般用于2个域名指向同一个网站. 一般来说,利用跳转,对网站的排名不会有影响.但不会转移 ...

  3. CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

    1.npm install -g increase-memory-limit 2.increase-memory-limit 3.重启解决

  4. 理解函数调用_使用argument参数

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 每日一抄 Go语言封装qsort快速排序函数

    package qsort /* <GO语言高级编程>设计中案例,仅作为笔记进行收藏. qsort快速排序函数是C语⾔的⾼阶函数,⽀持⽤于⾃定义排序⽐较函数,可以对任意类型的数组进⾏排序. ...

  6. express的安装,使用,请求,自动更新,静态资源托管(一)

    1.打开编辑器vscode 2.安装express   npm install express@4.17.1 3.创建文件index.js 4.导入express   const express = ...

  7. Godot从编辑器创建自定义场景类型对象

    Godot的编辑器提供了强大的所见即所得功能,并且,我们可以在不从源码编译的情况下,为编辑器提供新的节点类型. 首先,我们创建一个新场景,然后添加一个Node2D,然后为当前节点(Node2D)添加一 ...

  8. 【2020NOI.AC省选模拟#9】C. 重复

    题目链接 原题解: 通过计数相同的子序列对个数的方式来计算答案. 设$f(i,j)$为$S$的前$i$和$j$个字符的公共子序列对个数. 当$S_i=S_j$时,$f(i,j)=f(i,j-1)+f( ...

  9. 前端vue框架上手记录

    ---恢复内容开始--- Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供: 通过 @vue/cli 搭建交互式的项目脚手架. 通过 @vue/cli + @vue/cli-se ...

  10. Webpack解析与讲解

    一.什么是Webpack? 一个基于node.js的前端模块化/预处理/扁平化处理器. 二.为什么要使用Webpack? 解决业务代码中的各种依赖,模块加载,静态文件引入问题(重复依赖/强依赖,阻塞加 ...