• 第三篇文章:死锁


     两个线程互相占有了对方想要的资源,而且在互相等待对方释放占有的资源,因此都处于阻塞态

              

     线程A占有了资源2,并且想要资源资源1

    线程B占有了资源1,并且想要资源2

    代码实现

    线程 A 先是获得锁1,然后让线程 A 休眠 1s,这是为了让线程A不要一下子两把锁都拿到,给时间让B线程去拿锁2( 线程B开始执行),线程B获得锁2

    然后线程A想要获得被线程B占有的锁2,线程B想要获得被线程A占有的锁1

    1. Object obj1 = new Object();//资源 1
    2. Object obj2 = new Object();//资源 2
    3. Thread thread1=new Thread(() -> { synchronized (obj1) {
    4. System.out.println("Thread1 get obj1 lock");
    5. Thread.sleep(10);//这里暂停线程1是为了等待让线程2启动起来
    6. synchronized (obj2) {
    7. System.out.println("Thread1 is running");
    8. }
    9. }});
    10. Thread thread2= new Thread(() -> { synchronized (obj2) {
    11. System.out.println("Thread2 get obj2 lock");
    12. Thread.sleep(10);//这里暂停线程1是为了等待让线程2启动起来
    13. synchronized (obj1) {
    14. System.out.println("Thread2 is running");
    15. }
    16. }});
    17. thread1.start();
    18. thread2.start();

    死锁的四个必要条件:

    1. 互斥条件:该资源任意一个时刻只由一个线程占用。
    2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放  //也就是说不仅自己手里的资源抓住不放,还想要别人的资源,所以其实叫保持和请求更合适
    3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。//也就是别的线程不能强行剥夺另一个线程的资源
    4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

     通过破坏循环等待条件破坏死锁:

    两个线程申请锁的顺序本来是相反的,线程1先申请锁1,然后申请锁2,线程2先申请锁2,然后申请锁1

    现在调整为两个线程申请锁的顺序相同,线程1先申请锁1,然后申请锁2,线程2也是先申请锁1,然后申请锁2

    1. public class DeadLockDemo
    2. {
    3. Object obj1 = new Object();//资源 1
    4. Object obj2 = new Object();//资源 2
    5. public static void main(String[] args)
    6. {
    7. new Thread(() -> { synchronized (obj1)
    8. {
    9. Thread.sleep(1000);
    10. synchronized (obj2)
    11. {
    12. }
    13. }, "线程 1").start();
    14. new Thread(() -> { synchronized (obj1)
    15. {
    16. Thread.sleep(1000);
    17. synchronized (obj2)
    18. {
    19. }
    20. }, "线程 2").start();
    21. }
    22. }

    如何预防死锁?

    形成死锁的四个条件除了第一个互斥条件不能破坏,其他三个条件都可以破坏:

    1. 破坏请求与保持条件 :一次性申请所有的资源。(这样就不用再去请求别的线程占有的资源)
    2. 破坏不剥夺条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。(自己实在拿不到别的线程的资源,就把自己的贡献出去)
    3. 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

    如和避免死锁:银行家算法

  • 相关阅读:
    wangEditor 富文本编辑
    漏刻有时数据可视化Echarts组件开发(31):geomap伪3D配置示例
    扎实打牢数据结构算法根基,从此不怕算法面试系列之007 week01 02-07 简单的复杂度分析
    Java中如何遍历HashMap呢?
    vlan简单实验
    SSH项目集成DM达梦数据库
    MATLB|可视化学习(plot和bar)
    解决Redis、MySQL缓存双写不一致问题
    浅谈JavaScript中的forEach、for in和for of循环的基本用法和区别。
    AI制药,噱头还是未来?
  • 原文地址:https://blog.csdn.net/weixin_47414034/article/details/127121336