Java多线程死锁代码样例
题目
使用代码展示出两个线程死锁的情况
代码
public class Main {
private static final ReentrantLock LOCK_A = new ReentrantLock();
private static final ReentrantLock LOCK_B = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
//构建双线程死锁
Thread threadA = new Thread(() -> {
LOCK_A.lock();
try {
System.out.println("线程A获取到了锁A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOCK_B.lock();
try {
System.out.println("线程A获取到了锁B");
} finally {
LOCK_B.unlock();
}
} finally {
LOCK_A.unlock();
}
});
Thread threadB = new Thread(() -> {
LOCK_B.lock();
try {
System.out.println("线程B获取到了锁B");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOCK_A.lock();
try {
System.out.println("线程B获取到了锁A");
} finally {
LOCK_A.unlock();
}
} finally {
LOCK_B.unlock();
}
});
threadA.start();
threadB.start();
//构建死锁检测
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean a = LOCK_A.isLocked();
boolean b = LOCK_B.isLocked();
if (a && b) {
System.out.println("检测到死锁");
}
}
}
}
运行后,我们可以在控制台看到以下的输出:
线程A获取到了锁A
线程B获取到了锁B
检测到死锁
检测到死锁
检测到死锁
这样就成功完成死锁的场景呈现。
总结
在前面的代码中,我们实际上构建了满足以下要求的死锁场景:
互斥条件:资源是独占的且排他使用,进程互斥使用资源,即任意时刻一个资源只能给一个进程使用,其他进程若申请一个资源,而该资源被另一进程占有时,则申请者等待直到资源被占有者释放。
不可剥夺条件:进程所获得的资源在未使用完毕之前,不被其他进程强行剥夺,而只能由获得该资源的进程资源释放。
请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。
循环等待条件:在发生死锁时必然存在一个进程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路,环路中每一个进程所占有的资源同时被另一个申请,也就是前一个进程占有后一个进程所深情地资源
那么想要解决死锁,那就破环掉上述要求之一即可。
License:
CC BY 4.0