您的位置:首页 > 编程语言 > Java开发

Java多线程(五):死锁

2019-07-08 17:48 1771 查看

死锁

概念

当线程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会详细分析。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: