不好意思, 我要扳手, 不要班花 🛩️
- 死锁的必要条件
- 生动而形象的例子
- Java 中的死锁示例
死锁的必要条件
判断死锁的必要条件通常包括以下几点:
- 互斥条件:资源只能被一个进程(或线程)占有,无法被其他进程共享。
- 请求与保持条件:一个进程在请求新资源的同时,保持对已分配资源的占有。
- 不可剥夺条件:资源不能被强制从占有者手中回收,只能由占有者自愿释放。
- 循环等待条件:存在一个进程(或线程)等待序列,其中每个进程都在等待下一个进程释放资源。
生动而形象的例子
现在桌上摆着一把锤子, 一把扳手 // 互斥条件
我拿到了左手拿到一把锤子, 这时我准备去拿扳手 // 请求与保持条件
可这时我发现扳手被拿去开啤酒了, 而且他还想拿我的锤子开核桃
我不打算放弃, 你这拿去开啤酒开核桃明显不合理, // 不可剥夺条件,除非打架
我可是打算拿着锤子跟扳手去跟隔壁班花约会的
于是为了跟班花完美的约会, 于是我在这里等扳手
两个人一直耗到海枯石烂, 隔壁班花也有了自己的孩子 // 循环等待条件
于是你感慨死锁真是害人呀, 不说了, 继续等扳手了
Java 中的死锁示例
public class DeadlockExample {public static void main(String[] args) {final Object lock1 = new Object();final Object lock2 = new Object();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (lock1) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock2) {System.out.println("Thread 1 is holding lock 1 and lock 2.");}}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {synchronized (lock2) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock1) {System.out.println("Thread 2 is holding lock 1 and lock 2.");}}}});t1.start();t2.start();}
}
在上述代码中,有两个线程 t1 和 t2,它们同时试图获取 lock1 和 lock2 两个对象的锁,但获取锁的顺序不同。假设 t1 先获取了 lock1 的锁,然后在试图获取 lock2 的锁时被阻塞,而此时 t2 已经获取了 lock2 的锁,并试图获取 lock1 的锁,但 lock1 的锁已经被 t1 占用,因此 t2 也会被阻塞。这时候就产生了死锁,t1 和 t2 互相等待对方释放锁,导致程序无法继续执行。