线程的死锁和死锁解决的实际案例

尊重劳动成果,本文是参照https://blog.csdn.net/qq_38638148/article/details/82725191 然后再结合我自己的理解整理的,感谢博主的辛苦付出

造成死锁的原因:

  死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

死锁的解除:一旦检测出死锁,就应立即釆取相应的措施,以解除死锁。死锁解除的主要两种方法:

(1)抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以解除死锁状态。

(2)终止(或撤销)进程。终止(或撤销)系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态解脱出来。

先来看死锁:就是多个锁和多个线程之间发生的故事,这里以俩个锁和俩个线程为例子。

锁1、锁2、线程1、线程2

当线程1获取锁1之后,线程2也获取了锁2,这是线程1又开始获取锁2(嵌套获取),线程2又想获取锁1(嵌套1获取),这种情况下线程1会等着线程2释放锁2,线程2会等着线程1释放锁1,然后就会形成了死锁。

具体代码:


public class deadLock implements Runnable{

 

//1.创建俩把锁

public static final Object object1=new Object();

public static final Object object2=new Object();

  boolean boo;

@Override

public void run() {

  if(boo) {

  synchronized (object1) {

    System.out.println("进入1锁");

    try {

      Thread.sleep(1000);

     } catch (InterruptedException e) {

        e.printStackTrace();

    }

    synchronized (object2) {

      System.out.println("进入2锁");

    }

}

}else {

  synchronized(object2) {

  System.out.println("进入2锁");

  try {

    Thread.sleep(1000);

  } catch (InterruptedException e) {

    e.printStackTrace();

  }

        synchronized (object1) {

          System.out.println("进入1锁");

        }

      }

    } 

  }

}

测试代码


public static void main(String[] args) {

deadLock d1=new deadLock();

deadLock d2=new deadLock();

d1.boo=true;

d2.boo=false;

Thread t1=new Thread(d1);

Thread t2=new Thread(d2);

t1.start();

t2.start();

}

怎么解决呢?

这种解决方式可以有三种,

1.顺序取锁

2.设置锁释放时间(可以使用Lock来实现)

3.预防死锁

接下来贴出第一个方式的代码:


public class openLock implements Runnable{

 

public static final Object object=new Object();

public static final Object object1=new Object();

boolean bool;

@Override

public void run() {

if(bool) {

synchronized (object) {

System.out.println("进入1锁");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (object1) {

System.out.println("进入二锁");

}

}

}else {

synchronized (object) {

System.out.println("进入1锁");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (object1) {

System.out.println("进入2锁");

}

}

}

 

}

 

 

}

对比死锁的代码来看,其实就是让所有的线程获取所得顺序是一样的,这样子的话就不会存在什么线程死锁的情况出现。

第二种方法


public class OpenLock implements Runnable{

//第二种解决死锁的方式是:给锁设置一个时间,如果超过这个时间的或就放弃获取这个锁。

Lock l1=new ReentrantLock();//锁1

Lock l2=new ReentrantLock(); //锁2

boolean bool;

@Override

public void run() {

if(bool) {

try {

l1.lock();

System.out.println("加上锁1");

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("现在我在等待进入锁二了");

if(l2.tryLock(200, TimeUnit.MILLISECONDS)){//注意在判断这一步就已经加上锁了

try {

System.out.println("进入锁二");

}finally {

l2.unlock();

}

}else{

System.out.println("锁二一直被占用,算了我不进去了");

}

 

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

l1.unlock();

}

}else {

l2.lock();

try {

System.out.println("进入锁二");

Thread.sleep(1000);

System.out.println("现在我在等待进入锁1了");

if(l1.tryLock(200,TimeUnit.MILLISECONDS)) {

 

try {

System.out.println("进入锁一");

}finally {

l1.unlock();

}

}else {

System.out.println("等带时间太长了,我不等了。");

}

} catch (InterruptedException e) {

e.printStackTrace();

}finally {

 

}

}

 

}

 

}

 

这种方法就是利用Lock来实现的,Lock锁有一种说法叫做可中断锁,意思是当等待的线程达到一定的时间之后,就不会再去等待了,它会放弃运行这个锁方法,而去执行其他方法。

 

 

 

 

 

 

 

posted @ 2019-12-09 15:54  superming168  阅读(629)  评论(0编辑  收藏  举报