java多线程-死锁和死锁避免
程序员文章站
2022-05-22 11:21:21
...
一、死锁产生的四个必要条件
- 互斥条件:某个资源只能被一个进程使用,其他线程请求资源只能等待,直到当前线程释放资源(不可优化项)
- 占有并等待:进程已经保持一个资源,但是又提出了新要求,而这个资源被其他线程,自己保持的资源不被释放
- 不可枪占条件:一个进程的资源未使用完,不会释放资源
- 循环等待:线程获取资源存在一个循环链
二、死锁避免解决方案
- 破坏互斥:对于共享资源,我们要破坏互斥条件,例如多线程对于只读文件的读取操作
- 破坏占有并等待:当一个进程申请一个资源时,它不能占有其他资源。可以通过两种方式实现,方式一一个进程在执行前需要申请其所需的所有的资源。方式二,进程在没有资源时才可以申请。两种方式都有着缺点是会造成资源浪费和进程饥饿发生
- 破坏不可枪占条件:如果一个线程持有一些资源,那么如果继续请求其他资源的时候,发现不能请求成功,这个时候其他进程就可以枪占该进程的资源。
- 采用合适的进程推进顺序造成线程-银行家算法
三、银行家算法避免死锁
四、 一个死锁实例
package Concurrence;
/**
* Created by luckyboy on 2018/8/7.
*/
public class DeadLock {
public static void main(String[] args){
Common common = new Common();
Thread7 thread7 = new Thread7(common);
Thread8 thread8 = new Thread8(common);
thread7.start();
thread8.start();
}
}
class Thread7 extends Thread{
private Common common;
public Thread7(Common common){
this.common = common;
}
@Override
public void run(){
common.methodA();
}
}
class Thread8 extends Thread{
private Common common;
public Thread8(Common common){
this.common = common;
}
@Override
public void run(){
common.methodB();
}
}
class Common{
private Object obj1 = new Object();
private Object obj2 = new Object();
public void methodA(){
synchronized (obj1){
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"获取了当前obj1的锁");
synchronized(obj2){
System.out.println(Thread.currentThread().getName()+"获取了obj2的锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void methodB(){
synchronized (obj2){
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"获取了当前obj2的锁");
synchronized(obj1){
System.out.println(Thread.currentThread().getName()+"获取了obj1的锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出结果
五、线程运行查看工具jstack
打开PowerShell,运行下面的命令
PS C:\WINDOWS\system32> jstack
输出结果如下
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [aaa@qq.com]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
运行上面的语句我们可以获取一个线程的id、优先级、nid、是否是守护线程、线程的运行转态。
我们运行上面的DeadLockTest,然后去任务管理器查看我们的进程ID
在PowerShell中输入下面的命令
PS C:\WINDOWS\system32> jstack -l 11052
得到的输出结果如下
2018-08-07 09:21:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode):
"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003182800 nid=0x2f28 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001b88e000 nid=0x27dc waiting for monitor entry [0x000000001c5ff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Concurrence.DeadLock.methodB(DeadLockTest.java:59)
- waiting to lock <0x0000000780617130> (a java.lang.Object)
- locked <0x0000000780617140> (a java.lang.Object)
at Concurrence.Thread8.run(DeadLockTest.java:33)
Locked ownable synchronizers:
- None
"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001b88b000 nid=0x11c0 waiting for monitor entry [0x000000001c4ff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Concurrence.DeadLock.methodA(DeadLockTest.java:45)
- waiting to lock <0x0000000780617140> (a java.lang.Object)
- locked <0x0000000780617130> (a java.lang.Object)
at Concurrence.Thread7.run(DeadLockTest.java:23)
Locked ownable synchronizers:
- None
//......这里省略了GC线程和一些daemon线程信息
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x0000000003278618 (object 0x0000000780617130, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x000000000327ab38 (object 0x0000000780617140, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at Concurrence.DeadLock.methodB(DeadLockTest.java:59)
- waiting to lock <0x0000000780617130> (a java.lang.Object)
- locked <0x0000000780617140> (a java.lang.Object)
at Concurrence.Thread8.run(DeadLockTest.java:33)
"Thread-0":
at Concurrence.DeadLock.methodA(DeadLockTest.java:45)
- waiting to lock <0x0000000780617140> (a java.lang.Object)
- locked <0x0000000780617130> (a java.lang.Object)
at Concurrence.Thread7.run(DeadLockTest.java:23)
Found 1 deadlock.
线程信息解读
字段 | 信息解读 |
---|---|
Thread-1 | 线程名称 |
prio=5 | 线程优先级 |
tid=0x000000001b88e000 | 线程id |
java.lang.Thread.State: BLOCKED | java线程状态为阻塞状态 |
locked <0x0000000780617140> | 获得了<0x0000000780617140>这个对象 |
waiting to lock <0x0000000780617140> | 等待获取的对象的锁 |
上一篇: HDU - 5988 Coding Contest (费用流)
下一篇: 线程的同步与互斥