死锁的讲解
目录
1. 死锁定义
2. 死锁产生原因
3. 如何解决死锁问题
1. 死锁定义
死锁是指两个或两个以上的进程在执⾏过程中,由于竞争资源或者由于彼此通信⽽造成的⼀种阻塞的现象,若⽆外⼒作⽤,它们都将⽆法推进下去。(也就是两个线程拥有锁的情况下,⼜在尝试获取对⽅锁,从⽽造成程序⼀直阻塞的情况。)
2. 死锁产生原因
形成死锁主要由以下 4 个因素造成的: ① 互斥条件: ⼀个资源只能被⼀个线程占有,当这个资源被占⽤之后其他线程就只能等待。 ② 不可被剥夺条件: 当⼀个线程不主动释放资源时,此资源⼀直被拥有线程占有,其他线程不能得到此资源。 ③ 请求并持有条件: 线程已经拥有了⼀个资源之后,又尝试请求新的资源。 ④ 环路等待条件: 产⽣死锁⼀定是发⽣了线程资源环形链。 形成死锁,四个因素缺一不可。3. 如何解决死锁问题
打破产生死锁的一个或者多个条件即可。
① 互斥条件: 改变不了。 ② 不可被剥夺条件: 改变不了。 ③ 请求并持有条件: 可以改变(人为控制)。 ④ 环路等待条件: 可以改变(人为控制)。public class UnDeadLock {public static void main(String[] args) {Object lockA = new Object();Object lockB = new Object();Thread t1 = new Thread(() -> {synchronized (lockA) {System.out.println("线程1:得到锁A");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockB) {System.out.println("线程1:得到锁B");//业务代码System.out.println("线程1:释放锁B");}System.out.println("线程1:释放锁A");}},"线程1");t1.start();Thread t2 = new Thread(() -> {synchronized (lockB) {System.out.println("线程2:得到锁B");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockA) {System.out.println("线程2:得到锁A");//业务代码System.out.println("线程2:释放锁A");}System.out.println("线程2:释放锁A");}},"线程2");t2.start();}
}输出线程1:得到锁A线程2:得到锁B
(......没有结束)
上面代码产生了死锁。解决方法:
1. 修改获取锁请求并持有条件:
解决死锁方法:破坏请求并持有条件public class UnDeadLock {public static void main(String[] args) {Object lockA = new Object();Object lockB = new Object();Thread t1 = new Thread(() -> {synchronized (lockA) {System.out.println("线程1:得到锁A");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
// synchronized (lockB) {
// System.out.println("线程1:得到锁B");
// //业务代码
// System.out.println("线程1:释放锁B");
// }System.out.println("线程1:释放锁A");}},"线程1");t1.start();Thread t2 = new Thread(() -> {synchronized (lockB) {System.out.println("线程2:得到锁B");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
// synchronized (lockA) {
// System.out.println("线程2:得到锁A");
// //业务代码
// System.out.println("线程2:释放锁A");
// }System.out.println("线程2:释放锁B");}},"线程2");t2.start();}
}输出:线程1:得到锁A线程2:得到锁B线程2:释放锁B线程1:释放锁A
2. 修改获取锁的有序性来改变环路等待条件:
(使用顺序锁解决死锁问题)


解决死锁方法:修改获取锁的有序性来改变环路等待条件public class UnDeadLock2 {public static void main(String[] args) {Object lockA = new Object();Object lockB = new Object();Thread t1 = new Thread(() -> {synchronized (lockA) {System.out.println("线程1:得到锁A");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockB) {System.out.println("线程1:得到锁B");//业务代码System.out.println("线程1:释放锁B");}System.out.println("线程1:释放锁A");}},"线程1");t1.start();Thread t2 = new Thread(() -> {synchronized (lockA) {System.out.println("线程2:得到锁A");//业务代码try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockB) {System.out.println("线程2:得到锁B");//业务代码System.out.println("线程2:释放锁B");}System.out.println("线程2:释放锁A");}},"线程2");t2.start();}
}输出:线程1:得到锁A线程1:得到锁B线程1:释放锁B线程1:释放锁A线程2:得到锁A线程2:得到锁B线程2:释放锁B线程2:释放锁A
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
