没了解死锁怎么能行?进来看看,一文带你拿下死锁产生的原因、死锁的解决方案。

news2025/1/23 2:10:20

🌈🌈🌈今天给大家分享的是死锁产生的原因,以及如何解决死锁问题。

清风的CSDN博客

🛩️🛩️🛩️希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流!

✈️✈️✈️动动你们发财的小手,点点关注点点赞!在此谢过啦!哈哈哈!😛😛😛

目录

一、死锁是什么 

 二、哲学家就餐问题

三、如何避免死锁 

3.1 死锁产生的四个必要条件 

3.2 破除循环等待 

四、关于多线程的一些问题

4.1 谈谈 volatile关键字的用法? 

4.2 Java多线程是如何实现数据共享的? 

4.3 Java创建线程池的接口是,参数 LinkedBlockingQueue 的作用

4.4  Java线程共有几种状态?状态之间怎么切换的?

4.5 在多线程下,如果对一个数进行叠加,该怎么做? 

4.6 Thread和Runnable的区别和联系?

4.7 多次start一个线程会怎么样 

4.8 有synchronized两个方法,两个线程分别同时用这个方法,会发生什么?  

4.9 进程和线程的区别 


一、死锁是什么 

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
举个例子理解死锁
滑稽老哥和女神一起去饺子馆吃饺子,吃饺子需要酱油和醋。
滑稽老哥抄起了酱油瓶, 女神抄起了醋瓶。
滑稽: 你先把醋瓶给我, 我用完了就把酱油瓶给你。
女神: 你先把酱油瓶给我, 我用完了就把醋瓶给你。
如果这俩人彼此之间互不相让, 就构成了死锁.
酱油和醋相当于是两把锁, 这两个人就是两个线程。 

 为了进一步阐述死锁的形成, 很多资料上也会谈论到 "哲学家就餐问题"。

 二、哲学家就餐问题

  • 有个桌子, 围着一圈哲学家, 桌子中间放着一盘意大利面。每个哲学家两两之间, 放着一根筷子。

每个哲学家只做两件事: 思考人生或者吃面条。思考人生的时候就会放下筷子,吃面条就会拿起左
右两边的筷子(先拿起左边, 再拿起右边)。

 如果哲学家发现筷子拿不起来了(被别人占用了), 就会阻塞等待。

  • [关键点] 假设同一时刻, 五个哲学家同时拿起左手边的筷子, 然后再尝试拿右手的筷子, 就会发现右手的筷子都被占用了。由于哲学家们互不相让, 这个时候就形成了 死锁

死锁是一种严重的 BUG!! 导致一个程序的线程 "卡死", 无法正常工作!  

三、如何避免死锁 

3.1 死锁产生的四个必要条件 

  • 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。
  • 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  • 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  • 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

其中最容易破坏的就是 "循环等待"。 

3.2 破除循环等待 

最常用的一种死锁阻止技术就是 锁排序。 假设有 N 个线程尝试获取 M 把锁 , 就可以针对 M 把锁进行编号 (1, 2, 3...M)。

 N 个线程尝试获取锁的时候, 都按照固定的按编号由小到大顺序来获取锁. 这样就可以避免环路等待。

可能产生环路等待的代码:

两个线程对于加锁的顺序没有约定, 就容易产生环路等待。

Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread() {
    @Override
    public void run() {
        synchronized (lock1) {
            synchronized (lock2) {
                // do something...
           }
       }
   }
};
t1.start();
Thread t2 = new Thread() {
    @Override
    public void run() {
        synchronized (lock2) {
            synchronized (lock1) {
                // do something...
           }
       }
   }
};
t2.start();

 约定好先获取 lock1, 再获取 lock2 , 就不会环路等待。

Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread() {
    @Override
    public void run() {
        synchronized (lock1) {
            synchronized (lock2) {
                // do something...
           }
       }
   }
};
t1.start();
Thread t2 = new Thread() {
    @Override
    public void run() {
        synchronized (lock1) {
            synchronized (lock2) {
                // do something...
           }
       }
   }
};
t2.start();
}

四、关于多线程的一些问题

4.1 谈谈 volatile关键字的用法? 

volatile 能够保证内存可见性,强制从主内存中读取数据。此时如果有其他线程修改被 volatile 修饰的变量, 可以第一时间读取到最新的值。

4.2 Java多线程是如何实现数据共享的? 

JVM 把内存分成了这几个区域:
方法区, 堆区, 栈区, 程序计数器。
其中堆区这个内存区域是多个线程之间共享的。
只要把某个数据放到堆内存中, 就可以让多个线程都能访问到。

4.3 Java创建线程池的接口是,参数 LinkedBlockingQueue 的作用

创建线程池主要有两种方式:
  • 通过 Executors 工厂类创建,创建方式比较简单, 但是定制能力有限。
  • 通过 ThreadPoolExecutor 创建,创建方式比较复杂, 但是定制能力强。
LinkedBlockingQueue 表示线程池的任务队列,用户通过 submit / execute 向这个任务队列中添加任务, 再由线程池中的工作线程来执行任务。

4.4  Java线程共有几种状态?状态之间怎么切换的?

  • NEW: 安排了工作, 还未开始行动,新创建的线程, 还没有调用 start 方法时处在这个状态。
  • RUNNABLE: 可工作的。又可以分成正在工作中和即将开始工作,调用 start 方法之后, 并正在CPU 上运行/在即将准备运行的状态。
  • BLOCKED: 使用 synchronized 的时候, 如果锁被其他线程占用, 就会阻塞等待, 从而进入该状态。
  • WAITING: 调用 wait 方法会进入该状态。
  • TIMED_WAITING: 调用 sleep 方法或者 wait(超时时间) 会进入该状态。
  • TERMINATED: 工作完成了,当线程 run 方法执行完毕后, 会处于这个状态。

4.5 在多线程下,如果对一个数进行叠加,该怎么做? 

  • 使用 synchronized / ReentrantLock 加锁
  • 使用 AtomInteger 原子操作

4.6 ThreadRunnable的区别和联系?

  • Thread 类描述了一个线程。
  • Runnable 描述了一个任务。
  • 在创建线程的时候需要指定线程完成的任务, 可以直接重写 Thread 的 run 方法, 也可以使用Runnable 来描述这个任务。

4.7 多次start一个线程会怎么样 

  • 第一次调用 start 可以成功调用
  • 后续再调用 start 会抛出 java.lang.IllegalThreadStateException 异常

4.8 synchronized两个方法,两个线程分别同时用这个方法,会发生什么?  

synchronized 加在非静态方法上, 相当于针对当前对象加锁。
如果这两个方法属于同一个实例:
线程1 能够获取到锁, 并执行方法。线程2会阻塞等待, 直到线程1 执行完毕, 释放锁, 线程2 获取到锁之后才能执行方法内容。
如果这两个方法属于不同实例:
两者能并发执行, 互不干扰

4.9 进程和线程的区别 

  • 进程是包含线程的,每个进程至少有一个线程存在,即主线程。
  • 进程和进程之间不共享内存空间,同一个进程的线程之间共享同一个内存空间。
  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位。

🌈🌈🌈好啦,今天的分享就到这里!

🛩️🛩️🛩️希望各位看官读完文章后,能够有所提升。

🎉🎉🎉创作不易,还希望各位大佬支持一下!

✈️✈️✈️点赞,你的认可是我创作的动力!

⭐⭐⭐收藏,你的青睐是我努力的方向!

✏️✏️✏️评论:你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1279668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ORA-00257: archiver error. Connect internal only, until freed 的解决方法

归档文件存储空间不足,导致出现该问题。 当我们将数据库的模式修改为归档模式的时候,如果没有指定归档目录,默认的归档文件就会放到Flash Recovery Area的目录,但是这个目录是有大小限制的,如果超过了这个大小&#x…

专升本期间部分的C语言程序整理

说明 这些程序是我在专升本期间在CSDN上上传的作业、练习等,仅为学习备考的一小部分程序,整理成一篇文章,方便专升本的学弟学妹参考。 时间:2021年~2022年专升本期间 字符串题 输入字符串提取 数字字符 并 求和 (4处…

【排序】直接插入排序和希尔排序

目录 一、排序思想 1、直接插入排序 2、希尔排序 二、代码实现 三、性能比较 四、排序总结 1、直接插入排序 2、希尔排序 一、排序思想 1、直接插入排序 基本思想:把待排序的序列选取一个整数逐个插入到已经排好的有序序列中,直到所有整数都插入…

Android自定义View实现八大行星绕太阳转动效果

最近尝试使用Android自定义View实现了一个8大行星绕太阳转动的自定义View效果,效果静态图如下所示: 还没来得及对该效果进行比较通用的包装,仅仅实现效果,有兴趣的可以继续扩展、美化、包装一下。 核心代码就一个类PlanetsView。 …

ZLMediakit-method ANNOUNCE failed: 401 Unauthorized(ffmpeg、obs推流rtmp到ZLM发现的问题)

错误截图 解决办法:能推流成功,但是不能写入到wvp数据库中 修改配置文件config.ini 改成0 修改之后 重启服务 systemctl restart zlm*推流成功 解决办法:能推流,能写入数据库中 替换zlm版本,可以用我文章中提供的编译…

阅读软件OmniReader Pro mac功能特色

OmniReader Pro mac是一款文字识别和阅读软件,它可以将印刷体和手写体的文字转换为数字文本,并将其朗读出来。该软件适用于视力受损、阅读困难、语言障碍等用户,可以帮助他们更加轻松地获取信息和阅读文本。 OmniReader Pro具有简洁直观的用户…

为何全球电商都在拼“质价比”?

远在西雅图的希拉里,在著名的“黑色星期五”大促开始之前,她就已经准备好了一份购物清单。 然而,她发现身边的朋友们总是拉她组团购物。 在朋友和社交媒体的持续轰炸下,希拉里决定尝试一下这个让人贼上头的Temu。 最终&#xf…

linux之buildroot(3)配置软件包

Linux之buildroot(3)配置软件包 Author:Onceday Date:2023年11月30日 漫漫长路,才刚刚开始… 全系列文章请查看专栏: buildroot编译框架_Once_day的博客-CSDN博客。 参考文档: Buildroot - Making Embedded Linux Easymdev.t…

idea通过remote远程调试云服务器

引用了第三方的包,调试是看不到运行流程,于是想到了idea的remote方法 -agentlib:jdwptransportdt_socket,servery,suspendn,address9002 写一个.sh文件并启动 nohup java -jar -agentlib:jdwptransportdt_socket,servery,suspendn,address9002 ./demo.j…

vr工业制造流程3D模拟仿真可视化展示

工业仿真3D数字化展示系统具有多方面的独特之处,主要体现在以下几个方面: 1、真实感和交互性:该系统可以将实际的工业设备、产品、场景等进行数字化建模,通过三维图形技术将其呈现在计算机屏幕上,使用户可以在虚拟环境…

微信订阅号和服务号的区别

服务号和订阅号有什么区别?服务号转为订阅号有哪些作用?我们都知道,服务号一个月只能发4次文章,但是订阅号每天都能发文章。不过在接收消息这一方面,服务号群发的消息有消息提醒,并显示在对话框&#xff1b…

网络之路27:IRF设备堆叠

正文共:3210 字 34 图,预估阅读时间:5 分钟 目录 网络之路第一章:Windows系统中的网络 0、序言 1、Windows系统中的网络1.1、桌面中的网卡1.2、命令行中的网卡1.3、路由表1.4、家用路由器 网络之路第二章:认识企业设备…

使用策略模式彻底消除if-else

文章目录 使用策略模式彻底消除if-else1. 场景描述2. if-else方式3. 策略模式 使用策略模式彻底消除if-else 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现,这样会显得代码逻辑很臃肿&#xff0c…

TEMU三季度销售额或达50亿美金,多多跨境已成第二增长引擎

2023年11月28日,拼多多发布了2023年第三季度业绩报告。 报告显示,三季度的收入为688.4亿元,同比增长93.9%,按照美国通用会计准则,实现净利润155.4亿元,净利润率达到22.6%。 拼多多将近翻倍的业绩成长&…

mybatis整合(手动添加jar包方式)

操作步骤 创建数据库 建立user表 放入数据 1、创建javaweb工程并添加Jar包 用到的jar包 junit 用于测试 mybatis框架&#xff1a;mybatis-3.5.9.jar mysql数据库&#xff1a;mysql-connector-java-8.0.28.jar 2、添加MyBatis核心配置文件 <?xml version"1.0"…

19.字符串——查找三个字符串中的最大字符串(打擂台)

文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 四、举一反三总结 前言 本系列为字符串处理函数编程题&#xff0c;点滴成长&#xff0c;一起逆袭。 一、题目描述 查找三个字符串中的最大字符串 二、题目分析 打擂台 三、解题 程序运行代码 #include<…

linux进程优先级_nice

4.1.3.4 进程优先级&#xff1a;nice nice以更改过的优先序来执行程序&#xff0c;如果未指定程序&#xff0c;则会印出目前的排程优先序&#xff0c;内定的 adjustment 为 10&#xff0c;范围为 -20&#xff08;最高优先序&#xff09;到 19&#xff08;最低优先序&#xff0…

numpy实现神经网络

numpy实现神经网络 首先讲述的是神经网络的参数初始化与训练步骤 随机初始化 任何优化算法都需要一些初始的参数。到目前为止我们都是初始所有参数为0&#xff0c;这样的初始方法对于逻辑回归来说是可行的&#xff0c;但是对于神经网络来说是不可行的。如果我们令所有的初始…

编码相关的软技能,我看了这些书

大家好&#xff0c;我是老三&#xff0c;作为一个开发工程师&#xff0c;写代码是我们安身立命的根本&#xff0c;但是代码相关&#xff0c;代码之外&#xff0c;一些软技能也很重要&#xff0c;写代码很多时候决定能不能干活&#xff0c;软技能决定能不能干好活。 老三的编码…

外包干了2年,技术退步明显。。。

前言 简单的说下&#xff0c;我大学的一个同学&#xff0c;毕业后我自己去了自研的公司&#xff0c;他去了外包&#xff0c;快两年了我薪资、技术各个方面都有了很大的提升&#xff0c;他在外包干的这两年人都要废了&#xff0c;技术没一点提升&#xff0c;学不到任何东西&…