一、.死锁定义
死锁是指两个或两个以上的进程在执⾏过程中,由于竞争资源或者由于彼此通信⽽造成的⼀种阻塞的现象,若⽆外⼒作⽤,它们都将⽆法推进下去。
二、死锁产⽣的原因
形成死锁主要由以下 4 个因素造成的:
以下这四个条件缺一不可
① 互斥条件
⼀个资源只能被⼀个线程占有,当这个资源被占⽤之后其他线程就只能等待。
② 不可被剥夺条件
当⼀个线程不主动释放资源时,此资源⼀直被拥有线程占有,其它线程就得不到此资源。
③ 请求并持有条件
线程已经拥有了⼀个资源之后,有尝试请求新的资源。
④ 环路等待条件
产⽣死锁⼀定是发⽣了线程资源环形链。
三、解决死锁的思路
利用死锁的产生条件解决死锁问题
1.条件1是改变不了的
2.条件2也是改变不了的
3.条件3可以人认为控制,可以打破。
4.条件4可以打破也可以修改。
环路等待条件的破坏:使用顺序锁解决死锁问题
四、死锁产生示例
package Thread;
/**
* 死锁示例
*/
import java.util.concurrent.TimeUnit;
public class ThreadUnDeadLock1 {
public static void main(String[] args) {
Object lockA = new Object();
Object lockB = new Object();
Thread t1 = new Thread(()->{
// 1.占有一把锁(锁A)
synchronized(lockA){
System.out.println("线程1获得锁A");
//休眠1S让线程2获取锁B
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程2的锁B
synchronized(lockB){
System.out.println("线程1,获得锁B");
}
}
});
t1.start();
Thread t2 = new Thread(()->{
//占有一把锁B
synchronized(lockB){
System.out.println("线程2获取锁B");
// 休眠1s(保证线程1能有充足的时间得到锁A)
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(lockA){
System.out.println("线程2获取到了锁B!");
}
}
});
t2.start();
}
}
五、解决死锁示例
package Thread;
/**
* 使用顺序锁来解决循环死锁问题
*/
import java.util.concurrent.TimeUnit;
public class ThreadUnDeadLock2 {
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) {
}
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");
synchronized (lockB){
System.out.println("线程2得到了锁B");
//业务代码
System.out.println("线程2释放了锁B");
}
System.out.println("线程2释放了锁A");
}
},"线程2");
t2.start();
}
}