• 第三篇文章:死锁


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

              

     线程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. 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。

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

  • 相关阅读:
    社区系统项目复盘-7
    【超好用的工具库】hutool-all工具库的基本使用
    MySQL (2)
    洁净室悬浮粒子:手持式、在线式、便携式粒子计数器如何选择呢?
    Python-requests库入门指南
    【ESP32蓝牙通信】gatt_client 和 gatt_server 调试
    STM32开发从零开始(1)---手把手教你点亮一个LED灯
    Java 8 新特性 Stream 的使用场景(不定期更新)
    密码管理的艺术:数据库存储密码的策略、技术和工具
    【GDC】玩法设计
  • 原文地址:https://blog.csdn.net/weixin_47414034/article/details/127121336