glmapper

怎么写一个死锁?

字数统计: 748阅读时长: 3 min
2018/11/10 Share

刚把手头上的项目代码撸完,闲来看看博客,然后就看到了线程这块的东西。之前有简单的记录过线程和进行的零碎知识。

JAVA基础知识系列—进程、线程安全

看着看着就想着怎么能写一个死锁呢,打开eclipse,突然感觉无从下手;之前都是一直在解决阻塞、死锁这些问题,现在反过来去写一个死锁感觉有点莫名奇妙。。。

ok,写一个死锁就要有一种场景,并且满足死锁的条件。

  • 互斥条件:一个资源每次只能被一个进程使用。
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
  • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

首先要有竞争的资源,并且两个线程要同时都在等待对方释放资源。那我们先弄两个资源:

1
2
Object lock=new Object();
Object lock2=new Object();

然后有两个线程:

1
2
3
4
5
Tr1 tr1=new Tr1(lock, lock2);
Tr2 tr2=new Tr2(lock, lock2);

Thread t1=new Thread(tr1);
Thread t2=new Thread(tr2);

启动:

1
2
t1.start();
t2.start();

那么对于lock,lock2怎么再线程内部产生竞争关系呢?来看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.glmapper.base.synchronize;

public class Tr1 implements Runnable {

Object lock;
Object lock2;

public Tr1(Object lock,Object lock2){
this.lock= lock;
this.lock2= lock2;
}
@Override
public void run() {
//获取lock
synchronized (lock) {
System.out.println(Thread.currentThread().getName()+"获取了lock锁");
try {
Thread.sleep(3000);
} catch (Exception e) {
}
//获取lock2
synchronized (lock2) {
System.out.println(Thread.currentThread().getName()+"获取了lock2锁");
}
}

}
}


public class Tr2 implements Runnable {

Object lock;
Object lock2;

public Tr2(Object lock,Object lock2){
this.lock= lock;
this.lock2= lock2;
}
@Override
public void run() {
//获取lock2
synchronized (lock2) {
System.out.println(Thread.currentThread().getName()+"获取了lock2锁");
try {
Thread.sleep(3000);
} catch (Exception e) {
}
//获取lock
synchronized (lock) {
System.out.println(Thread.currentThread().getName()+"获取了lock锁");
}
}

}
}

分析一下:当线程1获取lock时,线程2获取了lock2锁;然后线程1继续执行,到这里,

1
2
3
synchronized (lock2) {
System.out.println(Thread.currentThread().getName()+"获取了lock2锁");
}

此时需要获取到lock2这个锁,但是lock2现在被线程2持有;同时,线程2也开始执行到:

1
2
3
synchronized (lock) {
System.out.println(Thread.currentThread().getName()+"获取了lock锁");
}

此时线程2也在尝试获取lock这把锁,但是lock又被线程1持有了。两个线程都在等待对方释放资源,造成了死锁。OK,完成了。。。

当我准备关机时,发现还在等呢?

??那为什么呢??
我们开看下发生了什么….

  • 通过jps来看下我们程序进程
  • 使用jstack -l 【pid】 来看下信息


两个线程都处于BLOCKED状态了…,继续往下看

found 1 deadlock.如我们所愿,死锁发生了!

原文作者:GuoLei Song

原文链接:http://www.glmapper.com/2018/11/10/java-base-thread-deadlock/

发表日期:November 10th 2018, 1:55:55 pm

更新日期:November 10th 2018, 1:56:34 pm

版权声明:转载请注明出处

CATALOG