一.什么是死锁
如果一组进程中的每一个进程都在等待仅由该组进程中的其它进程才能引发的事件,那么该组进程是死锁的。
二.产生死锁的常见情况
1.交叉锁
package com.btt.test;
public class DeadLock {
private Object A = new Object();
private Object B = new Object();
public void run() {
System.out.println("开始执行线程");
}
public Object getA() {
return A;
}
public void setA(Object a) {
A = a;
}
public Object getB() {
return B;
}
public void setB(Object b) {
B = b;
}
public static void main(String[] args) {
final DeadLock dl1 = new DeadLock();
Runnable r1 = new Runnable() {
public void run() {
synchronized (dl1.getA()) {
String tName = Thread.currentThread().getName();
System.out.println("我是线程" + tName + ",我拿到了A对象的锁");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我需要拿B对象的锁啦");
synchronized (dl1.getB()) {
System.out.println("线程1开始跑了");
}
};
}
};
Runnable r2 = new Runnable() {
public void run() {
synchronized (dl1.getB()) {
String tName = Thread.currentThread().getName();
System.out.println("我是线程" + tName + ",我拿到了B对象的锁");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我需要拿A对象的锁啦");
synchronized (dl1.getA()) {
System.out.println("线程2开始跑了");
};
};
}
};
Thread t1 = new Thread(r1);
t1.setName("t1");
t1.start();
Thread t2 = new Thread(r2);
t2.setName("t2");
t2.start();
}
}
2.内存不足
线程A使用10MB 系统剩余内存20MB,线程B使用30MB,内存不足造成死锁
3.一问一答的数据交换
server等待client访问
client发送请求到server,等待接收数据
4.死循环引起的死锁
HashMap引起的死锁
参考博文:https://blog.youkuaiyun.com/dingjianmin/article/details/79780350
三.死锁的避免,检测,形成原因
1.产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求和保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不可抢占条件:进程已获得的资源,在末使用完之前,不能强行剥夺,只能在进程使用完时由自己释放。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
2.死锁的预防
1)允许某些线程同时访问某些资源
2)允许线程强行去夺取某些资源
3)允许实现资源预分配策略
4)线程按照编号申请资源
3.死锁的解除:
一旦检测出死锁,就应立即釆取相应的措施,以解除死锁。死锁解除的主要两种方法:
- 抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态。
- 终止(或撤销)进程。终止(或撤销)系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态解脱出来。