java并发编程笔记(八)——死锁
死锁发生的必要条件
-
互斥条件
进程对分配到的资源进行排他性的使用,即在一段时间内只能由一个进程使用,如果有其他进程在请求,只能等待。
-
请求和保持条件
进程已经保持了至少一个资源,但是又提出了新的资源请求,而该资源又被其他进程占有,造成请求阻塞,但是又对自己已经占有的资源不放
-
不剥夺条件
是指进程在对已经占有的资源未使用完的情况下,不能被剥夺,只能在使用完时自己释放
-
环路等待条件
public class DeadLock implements Runnable {
public int flag = 1;
//静态对象是类的所有对象共享的
private static Object o1 = new Object(), o2 = new Object();
@Override
public void run() {
log.info("flag:{}", flag);
if (flag == 1) {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
log.info("1");
}
}
}
if (flag == 0) {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
log.info("0");
}
}
}
}
public static void main(String[] args) {
DeadLock td1 = new DeadLock();
DeadLock td2 = new DeadLock();
td1.flag = 1;
td2.flag = 0;
//td1,td2都处于可执行状态,但JVM线程调度先执行哪个线程是不确定的。
//td2的run()可能在td1的run()之前运行
new Thread(td1).start();
new Thread(td2).start();
}
}
避免死锁的措施
- 加锁顺序,要保持一致
- 加锁时间,设置超时时间
- 死锁检测,比较复杂