死锁的现象和解决办法
程序员文章站
2022-04-18 11:29:37
...
产生死锁的根本原因是两个或者两个以上线程在执行过程中,因争抢资源而产生相互等待的一种现象。在申请锁的时候发生了交叉闭环申请。
死锁产生的四个条件:
1)互斥。共享资源同时只能被一个线程访问。
2)占有且等待。线程T1在取得共享资源A的时候,请求等待资源B的时候并不释放资源A。
3)不可抢占。其他线程不能强行抢占线程的资源。
4)循环等待条件。线程T1在持有资源A1,同时在请求等待获取资源B,线程T2在持有资源B,然后在请求等待线程T1的持有资源,形成了交叉闭环申请。
处理死锁的方法可有以下4种:
1)死锁预防。由于互斥这个条件无法避免。操作系统本身所具有的特点。可对死锁产生的其他三个条件进行破坏。首先条件2,占有且等待,可以一次性申请所有的资源,可以破坏掉占有且等待。条件三不可抢占。当线程去请求其他资源时,如果获取不到锁,可以主动释放自己的锁,这样不可抢占的条件也被破坏掉了。条件四循环等待条件。可以对申请的资源进行编号,按序访问,这样线性的去申请资源,则不会造成交叉循环。
2)死锁避免。就不用去破坏形成死锁的其他条件。在资源动态分配的过程中。用某种方法判断防止进入不安全状态。从而避免发生死锁。可以使用银行家算法。死锁避免的算法会导致系统开销的增加。
3)死锁检测。死锁预防和死锁检测都是死锁发生之前的预防策略。死锁检测是通过系统设置的检测机构及时的判断当前系统是否处于死锁状态,并精确的确定当前死锁相关的进程和资源,执行死锁解除策略
4)死锁解除。这是与死锁检测结合使用的。它使用的方式是剥夺。就是讲进程所占有的资源强行收回,分配给其他进程。
首先实现一个死锁算法:
测试类:
@Test
public void test() {
Object o1 = new Object();
Object o2 = new Object();
MyThread thread = new MyThread(o1,o2);
MyThread2 thread2 = new MyThread2(o1,o2);
Thread thread1 = new Thread(thread);
Thread thread22 = new Thread(thread2);
thread1.start();
thread22.start();
}
class MyThread implements Runnable{
private Object o1;
private Object o2;
public MyThread(Object o1,Object o2) {
this.o1=o1;
this.o2=o2;
}
@Override
public void run() {
synchronized (o1){
System.out.println("我已经持有锁o1");
try{
Thread.sleep(500);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (o2){
System.out.println("我已经持有锁o2");
}
}
}
}
class MyThread2 implements Runnable{
private Object o1;
private Object o2;
public MyThread2(Object o1,Object o2) {
this.o1=o1;
this.o2=o2;
}
@Override
public void run() {
synchronized (o2){
System.out.println("我已经持有锁o2");
try{
Thread.sleep(500);
}catch (InterruptedException e){
e.printStackTrace();
}
synchronized (o1){
System.out.println("我已经持有锁o1");
}
}
}
}
上一篇: 2.flask用户登陆注册功能的实现