产生死锁的四个必要条件
四个必要条件
互斥条件:该资源任意⼀个时刻只由⼀个线程占⽤。
请求和保持条件:⼀个进程因请求资源⽽阻塞时,对已获得的资源保持不放。
不剥夺条件:线程已获得的资源在末使⽤完之前不能被其他线程强⾏剥夺,只有⾃⼰使⽤完 毕后才释放资源。
循环等待条件::若⼲进程之间形成⼀种头尾相接的循环等待资源关系。
代码演示
package com.lzp.test; /** * @Author 14715 * @Date 2022/6/6 16:21 * @Version 1.0 * * 死锁Demo */ public class DeadLockDemo { private static Object resource1 = new Object();//资源 1 private static Object resource2 = new Object();//资源 2 public static void main(String[] args) { new Thread(() -> { synchronized (resource1) { System.out.println(Thread.currentThread().getName() + "get resource1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "waiting get resource2"); synchronized (resource2) { System.out.println(Thread.currentThread().getName() + "get resource2"); } } }, "线程 1").start(); new Thread(() -> { synchronized (resource2) { System.out.println(Thread.currentThread().getName() + "get resource2"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "waiting get resource1"); synchronized (resource1) { System.out.println(Thread.currentThread().getName() + "get resource1"); } } }, "线程 2").start(); } }
运行结果
修改线程2的代码如下——破坏循环等待条件
package com.lzp.test; /** * @Author 14715 * @Date 2022/6/6 16:21 * @Version 1.0 * * 死锁Demo */ public class DeadLockDemo { private static Object resource1 = new Object();//资源 1 private static Object resource2 = new Object();//资源 2 public static void main(String[] args) { new Thread(() -> { synchronized (resource1) { System.out.println(Thread.currentThread().getName() + "get resource1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "waiting get resource2"); synchronized (resource2) { System.out.println(Thread.currentThread().getName() + "get resource2"); } } }, "线程 1").start(); new Thread(() -> { synchronized (resource1) { System.out.println(Thread.currentThread().getName() + "get resource1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "waiting get resource2"); synchronized (resource2) { System.out.println(Thread.currentThread().getName() + "get resource2"); } } }, "线程 2").start(); } }
运行结果
避免死锁的发生
- 破坏互斥条件 :这个条件我们没有办法破坏,因为我们⽤锁本来就是想让他们互斥的(临界 资源需要互斥访问)。
- 破坏请求与保持条件 :⼀次性申请所有的资源。
- 破坏不剥夺条件 :占⽤部分资源的线程进⼀步申请其他资源时,如果申请不到,可以主动释 放它占有的资源。
- 破坏循环等待条件 :靠按序申请资源来预防。按某⼀顺序申请资源,释放资源则反序释放。 破坏循环等待条件。