《泰坦尼克号》想必这么多年过去了依旧是无数人心目中的经典,不知有多少人,因为露丝与杰克的爱情故事而流泪,尤其是杰克为了让露丝能够安稳地活下去,自己甘愿献出生命,最终在冰冷的海水里,被活活地冻死。而露丝在多年后嫁为人妇,幸福地度过了后半生,完成了杰克的临终遗愿。
意外小插曲:爱情有时让人心情甜美但又充满磕磕碰碰。露丝和杰克都是鸭霸王的超级粉,下午露丝和杰克在船头夹板上嬉戏,露丝提议让杰克去餐厅打包一份鸭霸王。杰克打包"鸭霸王"的时候服务员只给了一双筷子。但杰克没有注意到,就屁颠屁颠的跑了夹板。问题来了只有一双筷子两个人怎么吃呢?
露丝和杰克嘴角同一时刻都露出了一丝狡黠的笑意,同时提议说到:那我们模仿微信抢红包,拼手速,谁先拿到谁先吃。那么此刻会出现如下3种情况:
1、露丝先拿到2只筷子,并开心的吃起了鸭霸王 (露丝胜利)
2、杰克先拿到2只筷子,并开心的吃起了鸭霸王 (杰克胜利)
3、杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让。(阻塞产生死锁)
一、产生死锁的条件
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
二、模拟死锁问题
(1) 程序模拟死锁
package com.demo.lock;
/**
* @author youyun.xu
* @ClassName: DeadLock
* @Description: 程序模拟死锁
* @date 2021/2/2 19:09
*/
public class DeadLock {
public static void main(String[] args) {
DeadLock deadLock = new DeadLock();
deadLock.titanic();
}
public void titanic(){
/*
* 死锁模拟场景:杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让。(阻塞产生死锁)
* */
Thread jack = new Thread( new Jack(),"杰克");
Thread rose = new Thread( new Rose(),"露丝");
jack.start();
rose.start();
}
//总共2根筷子[chopsticks1、chopsticks2]
Object chopsticks1 = new Object();
Object chopsticks2 = new Object();
class Jack implements Runnable{
@Override
public void run() {
synchronized (chopsticks1) {//杰克抢到了第1根筷子,开心的不要不要的
System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第一根筷子"));
sleep();
synchronized (chopsticks2) {//第2根筷子被“露丝”抢走,杰克在焦急等待,但露丝此刻没有丝毫想让出来的意思,因为她都很想吃鸭霸王。
System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第二根筷子"));
sleep();
}
}
}
public void sleep(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Rose implements Runnable{
@Override
public void run() {
synchronized (chopsticks2) { //露丝抢到了第2根筷子,开心的不要不要的
System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第二根筷子"));
sleep();
synchronized (chopsticks1) {//第1根筷子被“杰克”抢走,露丝在焦急等待,但“杰克”此刻没有丝毫想让出来的意思,因为他都很想吃鸭霸王。
System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第一根筷子"));
}
}
}
public void sleep(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(2) 程序模拟运行截图
三、系统如何排查死锁
Jconsole它是JDK自带的图形化界面工具,使用JDK给我们的的工具JConsole,本次就通过它排查死锁。
1、打开cmd然后输入Jconsole打开
2、与Jconsole 建立链接
3、点击检查死锁,并查看检查结果
四、思考题
1、杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让(阻塞产生死锁),如果你是中国版的杰克你该怎么做呢?
2、既然我们知道死锁产生的条件、同时用程序模拟观察了死锁的产生过程,请问该如何解决死锁问题?
当你觉得一切都为时已晚的时候,其实恰恰是最早的时候。