目录
1、什么是死锁
2、死锁的代码展示
3、死锁产生的原因
4、如何解决死锁问题
1、什么是死锁
死锁就是两个或两个以上线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
2、死锁的代码展示
也就是两个线程在各自拥有锁的情况下,又去尝试获取对方的锁,从而造成的一直阻塞的情况。
public class Thread18 { public static void main(String[] args) { Object lockA = new Object(); Object lockB = new Object(); Thread t1 = new Thread(() -> { // 1.占有一把锁(锁A) synchronized (lockA) { System.out.println("线程1:获得锁A。"); // 休眠 1s(让线程2有时间先占有锁B) try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 2.获取线程2的锁B synchronized (lockB) { System.out.println("线程1:获得锁B。"); } } }); t1.start(); Thread t2 = new Thread(() -> { // 1.占有一把锁(锁B) synchronized (lockB) { System.out.println("线程2:获得了锁B!"); // 休眠1s(保证线程1能有充足的时间得到锁A) try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } // 2.获取线程1的锁A synchronized (lockA) { System.out.println("线程2:获得了锁A!"); } } }); t2.start(); }}
3、死锁产生的原因
①互斥条件:一个资源只能被一个线程占有,当这个资源被占用后其他线程就只能等待。
②不可剥夺条件:当一个线程不主动释放资源时,此资源一直被拥有线程占有。
③请求并持有条件:线程已经拥有一个资源后仍然不满足,又尝试请求新的资源。
④环路等待条件:产生死锁一定是发生了线程资源环路链。
4、如何解决死锁问题
改变死锁中的任意一个或多个条件就可以解决死锁问题,其中被修改的条件只有后两个:请求并持有条件和环路等待条件。
修改请求并持有条件:获得了一把锁之后不再去请求获取另一把锁
破坏环路等待条件:如果就是需要两把锁的资源,则可以按照如下流程进行操作:
①线程1得到锁A,线程②进入阻塞状态。
②线程1去获取锁B,此时线程2仍然处于阻塞状态。
③线程1执行完毕,释放锁B,释放锁A。
④线程2获得锁A,继续执行。
⑤线程2获得锁B。
⑥线程2释放锁B。
⑦线程2释放锁A,执行结束。
实现代码:
/** * 解决死锁方案:破坏环路等待条件 */public class UnDeadLock2 { public static void main(String[] args) { Lock lockA = new ReentrantLock(); Lock lockB = new ReentrantLock(); Thread t1 = new Thread(()->{ synchronized (lockA){ System.out.println("线程1:得到了锁A"); //业务代码...... try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockB){ System.out.println("线程1:得到了锁B"); //业务代码..... System.out.println("线程1:释放了锁B"); } System.out.println("线程1:释放了锁A"); } },"线程1"); t1.start();//******************************************************** Thread t2 = new Thread(()->{ synchronized (lockA){ System.out.println("线程2:得到了锁A"); //业务代码...... try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockB){ System.out.println("线程2:获得了锁B"); //业务代码.... System.out.println("线程2:释放了锁B"); } System.out.println("线程2:释放了锁A"); } },"线程2"); t2.start(); }}