死锁产生条件
死锁的产生必须具备以下四个条件:
| 条件 | |
|---|---|
| 互斥 | 指线程对已经获取到的资源进行排它性使用,即该资源同时只由一个线程占用。如果此时还有其他线程请求获取该资源,则请求者只能等待,直至占有资源的线程释放该资源。 |
| 占有且等待 | 指一个线程已经持有了至少一个资源,但又提出了新的资源请求,而新资源已被其他线程占有,所以当前线程会被阻塞,但阻塞的同时并不释放自己已经获取的资源。 |
| 不可抢占 | 指线程获取到的资源在自己使用完之前不能被其他线程抢占,只有在自己使用完毕后才由自己释放该资源。 |
| 循环等待 | 指在发生死锁时,必然存在一个线程—资源的环形链,即线程集合{T0, T1, T2, …, Tn}中的T0正在等待一个T1占用的资源,T1正在等待T2占用的资源,……Tn正在等待已被T0占用的资源 |
package com.example.thread;/*** @Description:* @Author: baxiang* @Date: 2021/9/28.*/public class DeadLockTest {//1. 创建共享资源private static Object resourceA = new Object();private static Object resourceB = new Object();public static void main(String[] args) {//2. 创建线程AThread threadA = new Thread(new Runnable() {@Overridepublic void run() {//2.1获取资源A的锁synchronized (resourceA) {System.out.println(Thread.currentThread() + " get ResourceA");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//2.1获取资源B的锁System.out.println(Thread.currentThread() + "waiting get ResourceB");synchronized (resourceB) {System.out.println(Thread.currentThread() + "get ResourceB");}}}});//3. 创建线程BThread threadB = new Thread(new Runnable() {@Overridepublic void run() {//3.1获取资源B的锁synchronized (resourceB) {System.out.println(Thread.currentThread() + " get ResourceB");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//3.2获取资源A的锁System.out.println(Thread.currentThread() + "waiting get ResourceA");synchronized (resourceA) {System.out.println(Thread.currentThread() + "get ResourceA");}};}});//3. 启动线程threadA.start();threadB.start();}}
避免线程死锁
互斥这个条件我们没有办法破坏,因为我们用锁为的就是互斥,其他三个条件都有办法可以破坏
对于“占用且等待”这个条件,我们可以一次性申请所有的资源,这样就不存在等待了。
对于“不可抢占”这个条件,占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动
释放它占有的资源,这样不可抢占这个条件就破坏掉了。
对于“循环等待”这个条件,可以靠按序申请资源来预防。所谓按序申请,是指资源是有线性顺序
的,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样线性化后自然就不存在循环
了。
目前只有请求并持有和环路等待条件是可以被破坏的。
public class DeadLockBrokenTest {//1. 创建共享资源private static Object resourceA = new Object();private static Object resourceB = new Object();public static void main(String[] args) {//2. 创建线程AThread threadA = new Thread(new Runnable() {@Overridepublic void run() {//2.1获取资源A的锁synchronized (resourceA) {System.out.println(Thread.currentThread() + " get ResourceA");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//2.1获取资源B的锁System.out.println(Thread.currentThread() + "waiting get ResourceB");synchronized (resourceB) {System.out.println(Thread.currentThread() + "get ResourceB");}}}});//3. 创建线程BThread threadB = new Thread(new Runnable() {@Overridepublic void run() {//3.1获取资源A的锁synchronized (resourceA) {System.out.println(Thread.currentThread() + " get ResourceA");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//3.2获取资源B的锁System.out.println(Thread.currentThread() + "waiting get ResourceB");synchronized (resourceB) {System.out.println(Thread.currentThread() + "get ResourceB");}}}});//3. 启动线程threadA.start();threadB.start();}}
