死锁

概念

当线程Thread-0持有锁Lock1,Thread-1持有锁Lock2,此时Thread-0申请Lock2锁的使用权,Thread-1申请Lock1锁的使用权,Thread-0和Thread-1都在无限地等待锁的使用权。这样就造成了死锁。



死锁是主要由于设计的问题。一旦出现死锁,死锁的线程就会永远不能使用,同步方法不会被执行,死锁线程不会被自动终止,无尽地消耗CPU资源。

例子

看一个例子

ThreadDomain29类,模拟图片中,线程持有一个锁,申请被其他线程持有的锁的情况

public class ThreadDomain29 {
private final Object obj1 = new Object();
private final Object obj2 = new Object(); public void obj1obj2() throws Exception
{
synchronized (obj1)
{
Thread.sleep(2000);
synchronized (obj2)
{
System.out.println("obj1obj2 end!");
}
}
} public void obj2obj1() throws Exception
{
synchronized (obj2)
{
Thread.sleep(2000);
synchronized (obj1)
{
System.out.println("obj2obj1 end!");
}
}
}
}

MyThread29_0类

public class MyThread29_0 extends Thread{
private ThreadDomain29 dl; public MyThread29_0(ThreadDomain29 dl)
{
this.dl = dl;
} public void run()
{
try
{
dl.obj1obj2();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

MyThread29_1类

public class MyThread29_1 extends Thread{
private ThreadDomain29 dl; public MyThread29_1(ThreadDomain29 dl)
{
this.dl = dl;
} public void run()
{
try
{
dl.obj2obj1();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

main方法

public class MyThread29_main {
public static void main(String[] args)
{
ThreadDomain29 dl = new ThreadDomain29();
MyThread29_0 t0 = new MyThread29_0(dl);
MyThread29_1 t1 = new MyThread29_1(dl);
t0.start();
t1.start(); while(true);
}
}

因为发生了死锁,所以你不会看到任何结果。

死锁排查

jps+jstack

jps找到进程id



jstack打印堆栈

输入jstack 10208



可以看到,找到了两个死锁。

JConsole

命令行输入JConsole



点击“检测死锁”



已经检测到了死锁

Java Visual VM

命令行输入jvisualvm

找到我们的进程



自动检测到死锁,推荐使用这种方式

死锁避免

1.尽量少用嵌套的锁。

2.如果一定要用嵌套锁,那么请规定好获取锁的顺序。例子如下:

//伪代码
//condition1可以是属性值大小,hash值大小的比较等等
if(condition1){
synchronized (obj2)
{
Thread.sleep(2000);
synchronized (obj1)
{
System.out.println("obj2obj1 end!");
}
}
}else{
synchronized (obj1)
{
Thread.sleep(2000);
synchronized (obj2)
{
System.out.println("obj1obj2 end!");
}
}
}

3.使用Lock的tryLock方法,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。

后面讲到ReentrantLock会详细分析。

Java多线程(五):死锁的更多相关文章

  1. Java多线程(五) Lock接口,ReentranctLock,ReentrantReadWriteLock

    在JDK5里面,提供了一个Lock接口.该接口通过底层框架的形式为设计更面向对象.可更加细粒度控制线程代码.更灵活控制线程通信提供了基础.实现Lock接口且使用得比较多的是可重入锁(Reentrant ...

  2. java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)

    对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...

  3. java多线程(五)之总结(转)

    引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...

  4. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

  5. java多线程之死锁

    产生死锁的条件: 1.有至少一个资源不能共享2.至少有一个任务必须持有一个资源并且等待获取另一个被别的任务持有的资源3.资源不能任务抢占4.必须有循环等待 只要打破其中一个条件就不会产生死锁,通常是打 ...

  6. Java多线程和死锁

    一 .多线程: 售票窗口简单实例: public class SaleTicket { public static class Sale implements Runnable{ ; // @Over ...

  7. Java多线程:死锁

    周末看到一个用jstack查看死锁的例子.昨天晚上总结了一下jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令.供大家参考  1.Jstack 1.1 jstack能得到运行j ...

  8. Java 多线程(五)之 synchronized 的使用

    目录 1 线程安全 2 互斥锁 3 内置锁 synchronized 3.1 普通同步方法,锁是当前实例对象(this) 3.1.1 验证普通方法中的锁的对象是同一个. 3.1.2 验证不同的对象普通 ...

  9. JAVA多线程----用--死锁

    (1) 互斥条件:一个资源每次只能被一个进程使用.(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放.(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺.(4) ...

  10. Java多线程:线程死锁

    发生死锁的原因通常是两个对象的锁相互等待造成的. 以下用一个实例来构造这样的情况: package basic.e_deadlock; import org.apache.log4j.Logger; ...

随机推荐

  1. .NET Core 3.0 Preview 5 亮点之一:发布单文件可执行程序

    在阅读 Announcing .NET Core 3.0 Preview 5 时发现了 .NET Core 3.0 Preview 5 的一个新特性 —— Publishing Single EXEs ...

  2. jquery table 隔行变色+点谁谁变色

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  3. liunx 查看php 安装的扩展

    /usr/local/php5/bin/php -i |less 查看配置文件在哪里,编译参数 /usr/local/php5/bin/php -m |less 查看php加载的模块

  4. 如何将编码转为自己想要的编码 -- gbk utf-8

    /**  * 数组转码  * @param array $arr 要转码的数组  * @param string $in_charset 输入的字符集  * @param string $out_ch ...

  5. UWP入门(九)-- 枚举和查询文件和文件夹

    原文:UWP入门(九)-- 枚举和查询文件和文件夹 核心 API 所在的命名空间: Windows.Storage Windows.Storage.Streams Windows.Storage.Pi ...

  6. Android多线程(三)

    上次讲了关于Android多线程中通信中Thread.Handler.Looper等的基础概念和基本用法,用现实世界两个人写信交流的过程来理解是再好不过了.但是不得不说这一套完整的细节的确很繁琐,好在 ...

  7. UWP访问KnownFolders.RemovableDevices时(读取U盘文件)抛出异常UnauthorizedAccessException

    读取U盘的文件时: StorageFile file = await folder.GetFileAsync("myfile.txt"); 抛出异常System.Unauthori ...

  8. Android零基础入门第80节:Intent 属性详解(下)

    上一期学习了Intent的前三个属性,本期接着学习其余四个属性,以及Android系统常用内置组件的启动. 四.Data和Type属性 Data属性通常用于向Action属性提供操作的数据.Data属 ...

  9. 读取注册表获取Windows系统XP/7/8/10类型(使用wcscmp比较wchar[]内容)

    很多方案是采用GetVersion.GetVersionEx这两个API来查询操作系统的版本号来判断当前的操作系统是Windows系列中的哪个,在Win10没有出现前,这种方法是行的通的,但是Win1 ...

  10. zynqmp(zcu102rev1.0)系列---1---安装 xsdk

    Xilinx 的zynq7020在设备上面已经使用上,并量产,关于zynq7020使用总结将在近期同步进行. 该系列主要记录Xilinx zynqmp系列 的使用以及在遇到的问题.目前手上有一块dem ...