首页 > 其他分享 >#yyds干货盘点#什么是死锁以及如何解决死锁

#yyds干货盘点#什么是死锁以及如何解决死锁

时间:2023-08-02 10:32:25浏览次数:48  
标签:yyds Thread System 死锁 干货 线程 println out

死锁是指两个或多个线程在互相等待对方释放锁的状态,从而导致程序无法继续执行的情况。

在Java多线程中,死锁通常是由于以下四种情况的组合所导致的:

  1. 互斥:多个线程竞争同一资源(如锁),每次只能有一个线程占用,其他线程必须等待。
  2. 占有且等待:线程在持有锁的同时,等待其他线程持有的锁。
  3. 不可抢占:已经获取锁的线程不能被其他线程强制中断或释放锁。
  4. 循环等待:多个线程形成一个循环等待的关系,每个线程都在等待其他线程释放锁。

要解决死锁问题,可以采取以下措施:

  1. 避免使用多个锁:尽量使用单个锁或者使用更高级别的同步机制,比如并发集合。
  2. 统一获取锁的顺序:确保所有线程获取锁的顺序一致,避免出现循环等待的情况。
  3. 尽可能缩小同步代码块:减少同步代码块的长度,缩小互斥的范围。
  4. 及时释放锁:尽可能早地释放锁,避免占有且等待的情况。
  5. 使用定时锁:在获取锁时,使用带有超时时间的锁,避免因为等待锁而导致死锁。
  6. 强制中断线程:在发现死锁时,可以强制中断其中一个线程,打破循环等待的环。

需要注意的是,死锁是一个复杂的问题,解决起来也比较困难,需要仔细分析代码和调试。

public class DeadLock {
    public static void main(String[] args) {
        Object lockA = new Object();
        Object lockB = new Object();
 
        Thread t1 = new Thread(() -> {
            // 1.占有一把锁
            synchronized (lockA) {
                System.out.println("线程1获得锁A");
                // 休眠1s(让线程2有时间先占有锁B)
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取线程2的锁B
                synchronized (lockB) {
                    System.out.println("线程1获得锁B");
                }
            }
        });
        t1.start();
 
        Thread t2 = new Thread(() -> {
            // 占B锁
            synchronized (lockB) {
                System.out.println("线程2获得锁B");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 获取线程1的锁A
                synchronized (lockA) {
                    System.out.println("线程2获得了锁A");
                }
            }
        });
        t2.start();
    }
}

运行结果:

#yyds干货盘点#什么是死锁以及如何解决死锁_死锁

这段代码是一个典型的死锁示例,它包含两个线程,每个线程都持有一个锁并等待另一个锁的释放,从而导致死锁。

具体来说,这里定义了两个对象锁 lockA 和 lockB,并在两个线程中分别获取这两个锁。当线程1获取锁A后,它会休眠1秒钟,然后尝试获取锁B;而当线程2获取锁A后,它也会休眠1秒钟,然后尝试获取锁B。由于两个线程都在等待对方释放锁,因此它们会一直阻塞在获取锁的代码块中,无法继续执行,从而形成了死锁。

要解决这个问题,可以按照避免死锁的几种方法之一,例如对锁的获取顺序进行统一、尽量缩小同步代码块的范围、及时释放锁等。下面是一种修改方案:

public class UnDeadLock2 {
    public static void main(String[] args) {
        Object lockA = new Object();
        Object lockB = new Object();
 
        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();
    }
}

在修改后的代码中,两个线程都按照相同的顺序获取锁(先获取锁A,再获取锁B),从而避免了死锁问题。此外,线程2也及时释放了锁A,避免了占有且等待的情况。

运行结果:

#yyds干货盘点#什么是死锁以及如何解决死锁_同步代码块_02

标签:yyds,Thread,System,死锁,干货,线程,println,out
From: https://blog.51cto.com/u_11365839/6934242

相关文章

  • #yyds干货盘点#Java虚拟机基本结构
    类加载子系统类加载子系统负责从文件系统或网络中加载Class信息,加载的类的数据结构存放于一块叫方法区的内存空间中。方法区方法区主要存储类加载后的数据结构信息、运行时常量池信息、字符串、数字常量(这部分常量信息是Class文件中常量池部分的内存映射)(JDK1.7之前,JDK1.7之后字符......
  • MySQL加锁逻辑与死锁
    RC级别:create table t1(id int primary key, name varchar(30));insert into t1 values(1, 'a'),(4, 'c'),(7, 'b'),(10, 'a'),(20, 'd'),(30, 'b');commit;案例一--sess1           --sess2begin;              ......
  • RR 死锁一侧
    CREATE TABLE `t8` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `d_id` varchar(40) NOT NULL DEFAULT '',  `b_id` varchar(40) NOT NULL DEFAULT '',  `is_dropped` tinyint(1) NOT NULL DEFAULT '0',  `u_c` varchar(10) NOT NULL DEFA......
  • #yyds干货盘点#JavaScript正则表达式(手机号码、邮箱、日期)
    JavaScript正则表达式(手机号码、邮箱、日期)在平时的工作中,经常会遇到一些验证的功能,其中如号码、邮箱、日期之类的验证,但是在平常使用时,直接就抄了一份用,并没有很详细的研究过,所以就在这儿记录了一些常用的表达式,慢慢学习的同时,也分享给大家。手机号码由于现在虚拟号码的使用,所以......
  • #yyds干货盘点#python 正则表达式 re 模块总结
    使用爬虫爬取网页数据的过程中,需要利用各种工具解析网页中的数据,比如:etree,BeautifulSoup,scrapy 等工具,但是功能最强大的还是正则表达式,下面将对python的re模块方法做一个总结。Python 通过 re 模块提供对正则表达式的支持。使用 re 的一般步骤是:使用 re.compile(正则表......
  • # yyds干货盘点 # 使用Python统计下桌面某个文件夹下(含多层子文件夹)具体文件的数量(方
    大家好,我是皮皮。一、前言前几天在Python最强王者群【东哥】问了一个Python自动化办公的问题,一起来看看吧。这个是他自己在实际工作中遇到的需求,正好遇到了这个问题,想着用Python来实现下。二、实现过程上一篇文章中已经分享了一个方法,这一篇文章继续分享另外一个方法,由【巭孬嫑勥烎......
  • 用于查找 SQL Server 中死锁的 T-SQL 查询
    用于查找SQLServer中死锁的T-SQL查询 早些时候,我写了一篇关于使用扩展事件来查找SQLServer上发生的死锁的文章。扩展事件对于跟踪服务器上短时间内发生的死锁有很大帮助,尤其是在生产环境中。然而,在开发环境中,我遇到过当多个开发人员尝试对表执行dml语句时出现持续长......
  • 死锁
    1importthreading234#全局变量5g_num=0678#对g_num进行加操作9defsum_num1():10#上锁11print("sun_num1...")12print(f"sum_num1id(mutex){id(mutex)}")13mutex.acquire()1415foriinrange(100......
  • 北大AI公开课13讲全链接+最强干货盘点:视频+笔记+文字实录
    视频地址:北大AI公开课专栏笔记:北大AI公开课刚刚结束的北大AI公开课,由北大人工智能创新中心主任雷鸣组织,以把听者培养为“懂产业的AI人才”为主旨,邀请了13位顶级人工智能产业专家,分别从智能驾驶、智能医疗、智能金融、智能家居、硬件等10多个AI+行业,向学生和从业者全面介绍了......
  • 干货!Discord在Ubuntu中的安装方法
    Discord不仅仅是一个很好的聊天客户端。当你安装它时,你还可以获得其强大的服务端功能,强力而自足。游戏玩家和非玩家都可以在几分钟内开启自己的私人聊天服务,这使Discord成为团队、公会和各种社区的明显选择。Discord是一个非常受欢迎的文字和语音聊天程序。虽然开始时......