-
2019-09-11 11:49:41
死锁:是指多进程因循环等待资源而造成的无法执行的现象,它会造成进程无法执行,而且造成资源浪费
产生条件:
- 资源互斥使用:进程对分配到的资源进行排他性使用,即:某段时间内资源只能由一个进程使用,若其他进程想要使用该资源必须等待 直到该资源被释放。
- 资源不可抢占:指进程获得资源,在未使用完之前,不能被剥夺,只能在资源使用完毕后自己释放。
- 进程请求与保持:指进程已经获得至少一个资源,但有提出新的资源请求,而该资源被其他进程占用,此时进程阻塞。但对自己拥有的资源保持不放
- 进程循环等待:值在发生死锁时,必然存在进程–资源循环链。即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
避免方法:
- 银行家算法:判断此次请求是否造成死锁若会造成死锁,否则拒绝该请求
- 鸵鸟算法:忽略该问题,常用于在极少发生死锁的的情况
死锁的避免:通过合理的资源分配算法来确保永远不会形成环形等待的封闭进程链,即“如果一个进程的当前请求的资源会导致死锁,系统拒绝启动该进程;如果一个资源的分配会导致下一步的死锁,系统就拒绝本次的分配”
更多相关内容 -
java死锁程序
2021-02-28 17:17:57(1)死锁案例/*** 一个简单的死锁类* main方法中启动两个线程,分别调用methodA和methodB方法* methodA方法首先获取到a对象的锁,睡眠1秒钟* 此时methodB方法执行获取到b对象的锁,睡眠1秒* 此时methodA需要去获取b...(1)死锁案例
/*** 一个简单的死锁类
* main方法中启动两个线程,分别调用methodA和methodB方法
* methodA方法首先获取到a对象的锁,睡眠1秒钟
* 此时methodB方法执行获取到b对象的锁,睡眠1秒
* 此时methodA需要去获取b对象的锁才能继续执行,但是b锁没有被释放无法获取到
* 此时methodB需要去获取a对象的锁才能继续执行,但是a锁没有被释放无法获取到
* 从而两者相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。*/
public classDeadLock {private static String a = "1";private static String b = "2";public voidmethodA() {synchronized(a) {
System.out.println("我是A方法中获得到了A锁");try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}synchronized(b) {
System.out.println("我是A方法中获取到b锁");
}
}
}public voidmethodB() {synchronized(b) {
System.out.println("我是B方法中获得到了b锁");try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}synchronized(a) {
System.out.println("我是B方法中获取到a锁");
}
}
}public static voidmain(String[] args) {new Thread(() ->{
d.methodA();
}).start();new Thread(() ->{
d.methodB();
}).start();//new Thread(new Runnable() {//@Override//public void run() {//d.methodB();//}//}).start();}
}
(2)死锁
1、死锁的定义:进程中的每一个线程都在等待该组线程释放资源以此来运行自己,则该组进程是死锁的。
2、死锁产生的条件:
1)互斥条件:一段时间内某资源只由一个线程占用。如果此时还有其它线程请求资源,则请求者只能等待,直至占有资源的线程用毕释放。
2)请求和保持条件:线程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它线程占有,此时请求线程阻塞,但又对自己已获得的其它资源保持不放。
3)不可剥夺条件:线程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)循环且等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。
注意:打破四个必要条件之一就能有效预防死锁的发生。
3、死锁产生的原因
1)竞争资源引起进程死锁:
a、竞争不可剥夺资源:系统中只有一台打印机,可供进程P1使用,假定P1已占用了打印机,若P2继续要求打印机打印将阻塞
b、竞争临时资源:如缓冲区内的消息
2)进程间推进顺序非法
4、解决死锁的方法
1)预防死锁:
a、打破互斥条件:即允许进程同时访问某些资源。但是有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。
b、打破不可抢占条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。
c、打破占有且申请条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。
d、打破循环等待条件:实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源。
2)避免死锁:
银行家算法:当进程请求一组资源时,假设系统同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。
3)解除死锁:先检测是否有死锁,若有则解除死锁。
a、检测死锁:利用Jstack命令打印Java堆栈信息来定位线程出现长时间停顿的原因
b、解除死锁:若发现有线程死锁后,应立即把它从死锁状态中解除,方法如下:
剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
撤销线程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用即死锁状态解除为止;
-
Java死锁分析
2021-05-13 17:58:14死锁是多进程环境下的一种假死现象,即产生死锁的进程都处于等待状态。只要满足了下面四个必要条件,就有可能产生死锁:互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,...死锁是多进程环境下的一种假死现象,即产生死锁的进程都处于等待状态。只要满足了下面四个必要条件,就有可能产生死锁:
互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
环路等待条件:是指进程发生死锁后,必然存在一个进程–资源之间的环形链
一旦产生了死锁,程序将不再往下执行。那么应该怎么分析程序是否产生了死锁呢?本节来介绍一种使用Java Dump分析死锁的方法。
1.包含死锁的程序
下面是一段包含死锁的程序:DeadLock.java
public class DeadLock {
final Object lockA = new Object();
final Object lockB = new Object();
public static void main(String[] args) {
DeadLock demo = new DeadLock();
demo.startLock();
}
public void startLock(){
ThreadA a= new ThreadA(lockA,lockB);
ThreadB b= new ThreadB(lockA,lockB);
//start threads
a.start();
b.start();
}
}
class ThreadA extends Thread{
private Object lockA = null;
private Object lockB = null;
public ThreadA(Object a, Object b){
this.lockA = a;
this.lockB = b;
}
public void run() {
synchronized (lockA) {
System.out.println("*** Thread A: ***: Lock A" );
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockB) {
System.out.println("*** Thread A: ***: Lock B" );
}
}
System.out.println("*** Thread A: ***: Finished" );
}
}
class ThreadB extends Thread{
private Object lockA = null;
private Object lockB = null;
public ThreadB(Object a, Object b){
this.lockA = a;
this.lockB = b;
}
public void run() {
synchronized (lockB) {
System.out.println("*** Thread B: ***: Lock B" );
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lockA) {
System.out.println("*** Thread B: ***: Lock A" );
}
}
System.out.println("*** Thread B: ***: Finished" );
}
}
说明:以上代码中,有两个共享资源lockA和lockB,同时启动两个线程a和b,其中线程a先申请资源lockA,然后睡3秒,再去申请资源lockB;线程b先申请资源lockB,然后也睡3秒,再去申请资源lockA。当线程a启动并申请到资源lockA然后睡3秒时,这时线程b启动并申请到资源lockB也睡3秒;等线程a睡醒后去申请资源lockB,发现资源lockB被其他线程占用,所以线程a就开始等待;等线程b睡醒后去申请资源lockA,发现资源lockA也被其他线程占用,然后线程b也开始等待。如此这般,a和b就进入了循环等待的死锁状态。
2.使用JDK的Thread Dump工具分析死锁
这里介绍一种在Windows和Linux下,使用JDK提供的Thread Dump工具分析死锁的办法。
1.Windows下使用Thread Dump分析死锁
(1)编译并执行DeadLock.java程序
image
(2)按Ctrl + Break(或者fn + b)分析死锁
image
image
2.Linux下使用Thread Dump分析死锁
(1)编译并执行DeadLock.java程序
image
(2)使用kill -3 PID分析死锁
新打开一个终端,查看jps进程号,使用kill -3 PID杀死死锁进程:
image
原来的终端窗口会显示检测到的死锁信息:
image
死锁分析是一门非常重要的技术手段。使用Thread Dump工具可以方便的检测出程序是否包含死锁。
本节介绍了Java中使用Thread Dump工具分析死锁的详细过程。祝你玩的愉快!
-
java死锁排查
2021-03-15 03:22:32废话不多说,直接看下面死锁代码,这是一个典型的死锁,线程1拿到A锁获取B锁,线程2拿到B锁获取A锁public class DeadLockTest{private static Object A = new Object(), B = new Object();public static void main...废话不多说,直接看下面死锁代码,这是一个典型的死锁,线程1拿到A锁获取B锁,线程2拿到B锁获取A锁
public class DeadLockTest
{
private static Object A = new Object(), B = new Object();
public static void main(String[] args)
{
new Thread(() -> {
System.out.println("线程1开始执行...");
synchronized (A)
{
try
{
System.out.println("线程1拿到A锁");
//休眠两秒让线程2有时间拿到B锁
Thread.sleep(2000);
} catch (Exception e)
{
e.printStackTrace();
}
synchronized (B)
{
System.out.println("线程1拿到B锁");
}
}
}).start();
new Thread(() -> {
System.out.println("线程2开始执行...");
synchronized (B)
{
try
{
System.out.println("线程2拿到B锁");
//休眠两秒让线程1有时间拿到A锁
Thread.sleep(2000);
} catch (Exception e)
{
e.printStackTrace();
}
synchronized (A)
{
System.out.println("线程2拿到A锁");
}
}
}).start();
}
}
我们使用编译并运行这段代码,结果一目了然了
实际上线程1永远获取不到B锁,线程2永远获取不到A锁,问题如何排查解决呢。
方式一: 通过jps+jstack命令
我们可以通过jps命令(jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。)获取当前进程的id
id为6988的进程即使刚刚产生死锁的程序,我们记住这个id。使用jstack 命令去查看该线程的dump日志信息,如下图
可以看到标红的信息,此dump文件告诉了我们死锁发生的位置,我们就可以跟进代码继续去排查程序中的问题。
方式二:通过jconsole
在windons命令窗口 ,输出 JConsole,选择本地进程,选择DeadLockTest点下面的连接
点线程,点击检测死锁
同样可以定位到死锁信息,以及死锁发生的位置,如下图
方式三:使用jvisualvm
选择线程
点进去我们看下信息,会发现同样定位到了死锁相关信息,以及死锁发生的位置
-
JAVA中的死锁&解决方案
2021-06-14 14:09:24死锁出现的重要原因就是多个线程持有并等待锁,及线程1需要锁A、B,线程2也需要锁A、B,但是线程1先获取到了索引A,线程2先hou'o'qu -
java线程死锁的检测方法
2021-02-26 11:14:42#java线程死锁的检测方法Java中线程状态:新建(New)、可运行(Runnable)、等待(Wating)、超时等待(Timed_Wating)、阻塞(Blocked)、Terminated(终止)。所有状态在Thread.state枚举类中。状态转换图: 当线程中互相等待... -
Java线程死锁实例及解决方法
2021-03-15 23:57:17这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下1、死锁的定义所谓死锁是指多个线程因竞争资源而造成的一种僵局... -
Java解决线程死锁三种方案
2018-11-30 16:41:13死锁不仅仅在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞状态。 下面代码展示... -
Java——死锁
2021-05-18 15:00:42在JAVA编程中,有3种典型的死锁类型: 静态的锁顺序死锁 动态的锁顺序死锁 协作对象之间发生的死锁。 下面来一一介绍这三种死锁: 2. 静态的锁顺序死锁 a和b两个方法都需要获得A锁和B锁。一个线程执 -
进程死锁的检测
2011-12-26 17:14:59进程死锁的检测 建立资源分配图的数据结构描述; 建立绘制资源分配图的例程,包括结点和有向边; 可以删除、添加结点或有向边; 可用鼠标在窗口的任意位置指点,确定结点或有向边位置; 可以拖动现有结点的位置,与... -
java死锁原因和解决
2021-07-23 11:25:19死锁 简单点来说,两个或两个以上的线程情景下,线程A持有锁资源A,但是还想要资源B,于是请求B锁,线程B持有锁资源B,但是还想要资源A,于是请求A锁。两者互不释放锁,又想获得对方资源。 死锁条件 1、请求保持 2... -
java 解决死锁方法
2022-05-12 17:26:50死锁发生后,没有任何机制能解除死锁,只能强制结束JVM进程。 因此,在编写多线程应用时,要特别注意防止死锁。因为死锁一旦形成,就只能强制结束进程。 那么我们应该如何避免死锁呢? 答案是: 1.线程获取锁的顺序... -
Java中死锁问题如何排查
2022-03-11 22:17:55可以使用Java中自带的命令jps -l 用来查看当前运行的进程号,在使用jstack 进程号命令查看当前进程的堆栈信息 //死锁代码 class DeadLockRes { private String lock1 = "lockAA"; private String lock2 = "lockBB... -
Java死锁示例及检测
2021-02-28 14:11:14死锁是指多个线程在等待不可能被释放的锁,导致程序无法继续运行,下面用一个例子来说明。线程A持有lock1,在等待lock2,线程B持有lock2,在等待lock1,这样就发生了死锁。首先看一个类DealThread,这个类含有互斥锁... -
检查java线程死锁的几种方法
2021-02-12 09:40:55一.使用jconsolejconsole是jdk自带的内置java性能分析器,用来监控Java应用程序的性能和跟踪Java中的代码;... jconsole就可显示出GUI: 这里有一个死锁演示代码:package com.river.morethread;publi... -
java 死锁 解决_Java死锁故障排除和解决
2020-06-06 00:05:52java 死锁 解决 JavaOne年度会议的一大优点是主题专家介绍了几个技术和故障排除实验室。 这些实验室之一尤其引起了我的关注:Java冠军Heinz Kabutz提出的“ HOL6500-查找和解决Java死锁 ”。 这是我在该主题上看到... -
Java如何查看死锁
2021-02-27 07:43:19Java中当我们的开发涉及到多线程的时候,这个时候就很容易遇到死锁问题,刚开始遇到死锁问题的时候,我们很容易觉得莫名其妙,而且定位问题也很困难。因为涉及到java多线程的时候,有的问题会特别复杂,而且就算我们... -
什么是死锁,如何避免死锁?Java死锁详解
2020-12-20 15:54:03但在他们线程未执行完时,都不会释放AB资源,那么就形成了一种僵局,Thread1在等待Thead2施放B资源,Thread2在等待Thread1释放A资源,两个进程就形成了一种僵局,下面以Java代码实现为例说明: public class Dead... -
解决Java线程死锁问题及代码实例
2022-05-06 21:06:23解决Java线程死锁问题及代码实例。“死锁”是多线程中出现问题的一种情况,即:多个线程因竞争资源、进程推进顺序等原因而导致各进程同时被阻塞的情形,被阻塞的进程中一个或全部处于等待某个资源被释放达到自己执行... -
四个Java死锁检测工具
2022-03-25 17:07:42下面介绍一下如何排查Java中的死锁线程。 先来个死锁的例子: import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public ... -
Java如何查看死锁?
2021-02-28 14:10:26Java中当我们的开发涉及到多线程的时候,这个时候就很容易遇到死锁问题,刚开始遇到死锁问题的时候,我们很容易觉得莫名其妙,而且定位问题也很困难。因为涉及到java多线程的时候,有的问题会特别复杂,而且就算我们... -
怎么查看java进程?怎么检测线程死锁?线程状态
2020-09-16 02:35:04监控命令: jsp jstack pid,查看pid的所有线程状态信息 -
银行家算法(java实现)--避免进程死锁
2018-12-09 13:46:56public class Banker { /* * 资源的种类 ... * 进程的数量 */ private final int PROCESS_NUM = 3; /* * 可获取每种资源的数量的数组 */ private int[] available = new int[RESOUCE_NUM]; /... -
Java 查看死锁的方法
2021-03-09 20:04:271)连接到需要查看的进程。2)打开线程选项卡,然后点击左下角的“检测死锁”3)jconsole就会给我们检测出该线程中造成死锁的线程,点击选中即可查看详情:从上图中我们可以看出:①在线程Thread-1中,从状态可以看出,... -
操作系统进程死锁
2021-05-17 10:53:57如果一个进程集合中的每个进程都在等待只能由此集合中的其它进程所占有的资源,因而永远无法得到资源而陷入僵持,这种现象被称为进程死锁。 产生原因 产生死锁的原因有很多,如进程推进顺序不当、PV操作使用不妥、... -
如何解决java中的死锁问题
2021-03-06 20:47:39一、死锁的定义死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若...二、Java 代码模拟死锁代码示例:/*** 模拟死锁类* */public class ImitateDeadLock {public ... -
java死锁简单案例
2022-03-15 22:31:301、线程死锁的概念: 我们都知道,线程在执行的过程中是占着CPU的资源的,当多个线程都需要一个被锁住的条件才能结束的时候,死锁就产生了! 还有一个经典的死锁现象: 经典的“哲学家就餐问题”,5个哲学家吃中餐,... -
Java线程死锁查看分析方法
2021-02-28 15:50:28如何查看是否有Java线程死锁?下面介绍两种方法。一.JconsoleJconsole是JDK自带的图形化界面工具,使用JDK给我们的的工具JConsole,可以通过打开cmd然后输入jconsole打开。连接到需要查看的进程。打开线程选项卡,... -
关于Java避免死锁的几种方式
2021-03-07 00:15:59所谓线程,就是被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。在单线程程序下,我们总可以指出程序当前的运行位置。而对于多线程,就可以指出A线程运行到这里,B线程运行到这里,C线程运行... -
java线程死锁代码示例
2021-02-26 17:42:59死锁是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。事实上,计算机世界有很多事情需要多线程...