线程死锁
2021-04-22 15:29
标签:ack 演示 art 打印 资源释放 申请 拒绝 相互 strong 多个线程因竞争资源而造成的一种僵局(互相等待),无外力作用下程序无法推进的情况称之为死锁 如下图:线程P1拥有锁R1,请求锁R2,而线程P2拥有锁R2请求锁R1,彼此都请求不到资源,结束不了方法无法释放对方需要的资源,因此相互等待无法推进,这就是死锁 ? 进程要求对所分配的资源进行排他性控制,即该资源只能被一个进程占用,其他请求的进程只能等待占用资源的进程结束,释放资源 ? 进程已经获取了一个资源,在它使用完毕之前,无法被其他进程剥夺走,只能由获取该资源的进程主动释放资源 ? 进程当前已经获取了一个资源,但又提出了一个新的资源请求,而新的资源被占用了,此时请求被阻塞, 当前获取的的资源也无法释放 ? 多个进程呈环形互相等待的情况称为循环等待,出现死锁的时候一定是循环等待的情况,但是循环等待不一定就是死锁,但这个闭环中的某个进程请求的资源不仅仅只有一个请求途径,环形外有进程也释放它请求的资源,则可以跑出闭环,则不是死锁 以下实现一个死锁: 通过两个线程互相等待的情况来演示 创建启动线程进行测试: 发生死锁 死锁的预防是严格控制产生死锁的必要条件的存在,而避免是不严格控制,因为就算满足了必要条件也不一定会发生死锁,如果这样限制的话,系统的性能将会降低,因此通过一些更优的算法,来避免产生死锁,就算条件满足也不会发生死锁。 为所有资源统一编号,所有的线程在请求不同资源时都得按顺序请求 同类资源则要一次请求完毕,即同一台设备的机器打印机传真机要同时申请 举个例子: 现有两个进程P1,P2,两个资源R1,R2,P1和P2都要请求R1,R2,假设P1先获取到了R1,那么P2就不能先去请求R2,必须等待P1释放R1资源,以此来避免死锁 银行家算法结构的逻辑如下: 分析: ? 预防和避免死锁系统开销大且不能充分利用资源,更好的方法是不采取任何限制性措施,而是提供检测和解脱死锁的手段,这就是死锁的检测和恢复 死锁检测的数据结构 死锁检测步骤 线程死锁 标签:ack 演示 art 打印 资源释放 申请 拒绝 相互 strong 原文地址:https://www.cnblogs.com/JIATCODE/p/13276343.html线程死锁
1.死锁
2.产生的四个必要条件
1. 互斥条件
2.不可剥夺条件
3.请求与保持条件
4.循环等待条件
3.死锁演示
public class Locks implements Runnable{
private int flag; //用来引导两个线程调用不同的资源
//这里要对两个锁定义static,必须是请求共享资源才会引发死锁
public static Lock lock = new ReentrantLock();
public static Lock lock2 = new ReentrantLock();
public Locks(int flag){
this.flag = flag;
}
public void run() {
if (flag==1) {
//请求锁1
lock.lock();
try {
System.out.println("线程1请求锁2");
//持有锁1的时候请求锁2
lock2.lock();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
lock2.unlock();
}
}else{
lock2.lock();
try {
System.out.println("线程2请求锁1");
lock.lock();
Thread.sleep(1000);
} finally {
lock.unlock();
lock2.unlock();
}
}
}
}
public class Demo {
public static void main(String[] args) {
Thread thread = new Thread(new Locks(1));
Thread thread2 = new Thread(new Locks(2));
thread.start();
thread2.start();
}
}
4.处理死锁
1.预防
2.避免
1. 有序资源分配法
2.银行家算法
3.顺序加锁
4.限时加锁
3.检测
4.恢复
抢占
回滚
杀死进程(不推荐)
下一篇:学java的第四天