0
点赞
收藏
分享

微信扫一扫

并发编程之死锁


死锁

死锁就是两个或以上线程互相争抢对方资源,导致没有任何一个线程能获得所需所有资源的一种僵持状态。死锁下的线程是 BLOCKED 状态。

下面我们来使用Synchronized 关键字 造一个死锁。

ServiceOne类:

public class ServiceOne {
private ServiceTwo serviceTwo;
private final Object LOCK_ONE = new Object();

public void setServiceTwo(ServiceTwo serviceTwo) {
this.serviceTwo = serviceTwo;
}

public void soMethod1(){
synchronized (LOCK_ONE){
System.out.println("soMethod1 get LOCK_ONE.");
System.out.println("handle soMethod1.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
serviceTwo.stMethod1();
}
}

public void soMethod2(){
synchronized (LOCK_ONE){
System.out.println("soMethod2 get LOCK_ONE.");
System.out.println("handle soMethod2.");
}
}
}

ServiceTwo类:

public class ServiceTwo {
private ServiceOne serviceOne;
private final Object LOCK_TWO = new Object();

public void setServiceOne(ServiceOne serviceOne) {
this.serviceOne = serviceOne;
}

public void stMethod1() {
synchronized (LOCK_TWO){
System.out.println("stMethod1 get LOCK_TWO");
System.out.println("handle.");
}
}

public void stMethod2(){
synchronized (LOCK_TWO){
System.out.println("stMethod2 get LOCK_TWO.");
System.out.println("handle stMethod2.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
serviceOne.soMethod2();
}
}
}

测试代码:

public class TestService {

public static void main(String[] args) {
ServiceOne serviceOne = new ServiceOne();
ServiceTwo serviceTwo = new ServiceTwo();
serviceOne.setServiceTwo(serviceTwo);
serviceTwo.setServiceOne(serviceOne);

new Thread(){
@Override
public void run() {
serviceOne.soMethod1();
}
}.start();
new Thread(){
@Override
public void run() {
serviceTwo.stMethod2();
}
}.start();
}
}

输出结果:

soMethod1 get LOCK_ONE.
handle soMethod1.
stMethod2 get LOCK_TWO.
handle stMethod2.

然后线程一直等待。

分析:

首先我们假设线程1和线程2同时启动(虽然不是同时启动,但是相差远小于1s)

并发编程之死锁_死锁

通过上图可以知道,线程1持有​​LOCK_ONE​​​, 想获取​​LOCK_TWO​​​, 而线程2持有​​LOCK_TWO​​​, 想获取​​LOCK_ONE​​, 所以导致了死锁。

下面我们通过 jstack 查看线程情况。

首先使用命令​​jps​​ 查询线程。

F:\1SourceCode\java-concurrency> jps
12036 Jps
12600
22824 TestService
8104 org.eclipse.equinox.launcher_1.5.700.v20200207-2156.jar
11196 Launcher

然后使用​​jstack​

F:\1SourceCode\java-concurrency>jstack 22824
2020-05-15 21:56:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.91-b15 mixed mode):

...

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000002f62800 nid=0x5eac waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001ebc9000 nid=0x6248 waiting for monitor entry [0x000000001f99e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod2(ServiceOne.java:30)
- waiting to lock <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod2(ServiceTwo.java:27)
- locked <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$2.run(TestService.java:20)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001ebc8000 nid=0x4584 waiting for monitor entry [0x000000001f89f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod1(ServiceTwo.java:13)
- waiting to lock <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod1(ServiceOne.java:23)
- locked <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$1.run(TestService.java:14)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001eb15800 nid=0x6320 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
...
JNI global references: 362


Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x000000000305dff8 (object 0x000000076b3b44f8, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000305b768 (object 0x000000076b3b7a20, a java.lang.Object),
which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod2(ServiceOne.java:30)
- waiting to lock <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod2(ServiceTwo.java:27)
- locked <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$2.run(TestService.java:20)
"Thread-0":
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod1(ServiceTwo.java:13)
- waiting to lock <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod1(ServiceOne.java:23)
- locked <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$1.run(TestService.java:14)

Found 1 deadlock.

可以看到 ​​Found 1 deadlock​​​. 表示发现一个死锁。我们再拿出我们创建的 ​​Thread-0​​​ 和 ​​Thread-1​​ 两个线程信息分析:

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001ebc9000 nid=0x6248 waiting for monitor entry [0x000000001f99e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod2(ServiceOne.java:30)
- waiting to lock <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod2(ServiceTwo.java:27)
- locked <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$2.run(TestService.java:20)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001ebc8000 nid=0x4584 waiting for monitor entry [0x000000001f89f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.example.chapter8.deadLockDemo.ServiceTwo.stMethod1(ServiceTwo.java:13)
- waiting to lock <0x000000076b3b7a20> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.ServiceOne.soMethod1(ServiceOne.java:23)
- locked <0x000000076b3b44f8> (a java.lang.Object)
at org.example.chapter8.deadLockDemo.TestService$1.run(TestService.java:14)

可以看到 ​​Thread-1​​ locked <0x000000076b3b7a20> , waiting to lock <0x000000076b3b44f8>, 而 ​​Thread-0​​ locked <0x000000076b3b44f8> , waiting to lock <0x000000076b3b7a20> , 这里也可以明显的看到锁的信息。 并且都处于BLOCKED状态。所以死锁情况下的线程处于 BLOCKED .


举报

相关推荐

0 条评论