《Java-SE-第三十章》之哲学家就餐问题
前言
在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”
博客主页:KC老衲爱尼姑的博客主页
博主的github,平常所写代码皆在于此
共勉:talk is cheap, show me the code
作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
文章目录
- 死锁
- 哲学家就餐问题
- 死锁复现
- 解决办法
死锁
当某个任务在等待另一个任务,而后者又等待别的任务,这样一直下去,直到这个链条上的任务又在等待第一个任务释放锁。这得到了一个任务之间互相等待的连续循环, 没有那个线程能继续,这称之为死锁。举个栗子,张三想要回家,当开门的时候,发现没钥匙,此时张三突然想起,屋子钥匙放在了车里面,而车的钥匙在房子里面,想要进入就得打开车子,想要打开车子,必须的进屋子,这就"死锁"了。
示例代码
public class DeadlockDemo {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(() -> {synchronized (A) {System.out.println("lock A");try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (B) {System.out.println("lock B");}}});t1.start();Thread t2 = new Thread(() -> {synchronized (B) {System.out.println("lock B");try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (A) {System.out.println("lock A");}}});t2.start();}
}
通过使用jconsole观察两个线程的状态

通过观察可知都死锁了
哲学家就餐问题
哲学家就餐问题由Edsger Dijkstra提出的,该问题是一个经典的死锁问题,该问题的基本描述中是指定五个哲学家。这些哲学家将花部分时间思考,花部分时间就餐。当他们思考的时候,不需要任何共享资源;但当他们就餐时,将使用有限数量的餐具。在问题的原始描述中,餐具是叉子。要吃到桌子中央盘子里的意大利面条需要用两把叉子,不过把餐具看成是筷子更合理;很明显,哲学家要就餐就需要两根筷子。问题中引入的难点是:作为哲学家,他们很穷,所以他们只能买五根筷子(更一般地讲,筷子和哲学家的数量相同)。他们围坐在桌子周围,每人之间放一根筷子。当一个哲学家要就餐的时候,这个哲学家必须同时得到左边和右边的筷子。上述问题会产生死锁的情况,当5个哲学家都拿起自己左或者右手手边的筷子,准备拿右手或者左手边的筷子时产生死锁现象。

代码演示
- 定义一个筷子类
public class Chopstick {private String name;public Chopstick(String name) {this.name = name;}
}
- 定义哲学家
public class Philosopher implements Runnable {/*** 左手筷子*/private Chopstick left;/*** 右手筷子*/private Chopstick right;/*** 名字*/private String name;public Philosopher(Chopstick left, Chopstick right, String name) {this.left = left;this.right = right;this.name = name;}public void thinking() {System.out.println(this.name + " " + "thinking");}public void eating() {System.out.println(this.name + " " + "eating");}@Overridepublic void run() {while (!Thread.interrupted()) {thinking();synchronized (this.right) {synchronized (this.left) {eating();}}}}
}
死锁复现
import java.io.IOException;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;public class DeadLockPhilosopher {public static void main(String[] args) throws InterruptedException, IOException {int size = 5;ExecutorService exec = Executors.newCachedThreadPool();Chopstick [] sticks = new Chopstick[size];for (int i = 0; i < sticks.length;i++){sticks[i] = new Chopstick(i+"号筷子");}for (int i = 0; i < size;i++) {exec.execute(new Philosopher(sticks[i], sticks[(i+1) % size],i+"号哲学家"));}TimeUnit.SECONDS.sleep(10);exec.shutdownNow();}
}
运行结果:

代码先是正常运行了一会,然后将就死锁了,是否死锁依旧用jconsole观察,观察结果如下图

解决办法
要修正死锁问题,你必须明白,当以下四个条件同时满足时,就会发生死锁:
- 互斥条件。任务使用的资源中至少有一个是不能共享的。这里,一根Chopstick一次就只能被一个Philosopher使用。
- 请求和保持,至少有一个任务它必须持有一个资源且正在等待获取一个当前被别的任务持有的资源。也就是说,要发生死锁,Philosopher必须拿着一根Chopstick并且等待另一根。
- 资源不能被任务抢占,任务必须把资源释放当作普通事件。Philosopher很有礼貌,他们不会从其他Philosopher那里抢Chopstick
- 必须有循环等待,这时,一个任务等待其他任务所持有的资源,后者又在等待另一个任务所持有的资源,这样一直下去,直到有一个任务在等待第一个任务所持有的资源,使得大家都被锁住。在DeadlockingDiningPhilosophers.java中,因为每个Philosopher都试图先得到右边的Chopstick,然后得到左边的Chopstick,所以发生了循环等待。
因为要发生死锁的话,所有这些条件必须全部满足;所以要防止死锁的话,只需破坏其中一个即可。在程序中,防止死锁最容易的方法是破坏第4个条件。有这个条件的原因是每个Philosopher都试图用特定的顺序拿Chopstick:先右后左。正因为如此,就可能会发生“每个人都拿着右边的Chopstick,并等待左边的Chopstick”的情况,这就是循环等待条件。然而,如果最后一个Philosopher被初始化成先拿左边的Chopstick,后拿右边的Chopstick,那么这个Philosopher将永远不会阻止其右边的Philosopher拿起他们的Chopstick。
示例代码
import java.util.concurrent.*;public class FixedDiningPhilosophers {public static void main(String[] args) throws Exception {ExecutorService exec = Executors.newCachedThreadPool();Chopstick[] sticks = new Chopstick[5];int size = 5;for (int i = 0; i < sticks.length; i++) {sticks[i] = new Chopstick(i + "号筷子");}for (int i = 0; i < sticks.length; i++) {//前四个哲学家if (i < (size - 1)) {exec.execute(new Philosopher(sticks[i], sticks[(i + 1)], i + "哲学家"));} else {exec.execute(new Philosopher(sticks[0], sticks[(i)], i + "哲学家"));}}TimeUnit.SECONDS.sleep(5);exec.shutdownNow();}
}
运行结果:

由此就解决了哲学家就餐问题中的死锁
各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

相关文章:
《Java-SE-第三十章》之哲学家就餐问题
前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限&…...
关于接口测试用例设计的一些思考
接口测试发现的典型问题 传入参数处理不当,引起程序错误类型溢出,导致数据读取和写入不一致对象权限校验出错,可获取其他角色信息状态出错,导致逻辑处理出现问题逻辑校验不完善定时任务执行出错 接口测试用例设计 接口测试用例…...
gin和gorm框架安装
理论上只要这两句命令 go get -u gorm.io/gorm go get -u github.com/gin-gonic/gin然而却出现了问题 貌似是代理问题,加上一条命令 go env -w GOPROXYhttps://goproxy.cn,direct 可以成功安装 安装gorm的数据库驱动程序 go get -u gorm.io/driver/mysql...
今天小编继续给大家分享五款高效的电脑宝藏软件
目录 1、keytweak 2、ScreenToGif 3、Greenshot截屏工具 4、GIMP 5、HandBrake 1、keytweak keytweak 简单来说就是一个键盘按键修改器,说白了就是一个键盘按键重映射的软件。比如你键盘上的Q不好用了,你可以更换成一个不常见的按键来代替Q键&#x…...
SQL Server数据库如何添加mysql链接服务器(Windows系统)
SQL Server数据库如何添加mysql链接服务器(Windows系统) 一、说明二、下载mysql的odbc驱动三、安装mysql odbc四、配置ODBC4.1 控制面板→ODBC数据源(64位)→双击打开4.2 添加msql odbc数据源 五、测试添加是否成功六、打开SSMS&a…...
scala连接mysql数据库
scala中通常是通过JDBC组件来连接Mysql。JDBC, 全称为Java DataBase Connectivity standard。 加载依赖 其中包含 JDBC driver <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29&l…...
datax-web登陆时出现账号密码错误
在查找问题时,在admin里面查看日志时: 目录的位置:datax-web-2.1.2/modules/datax-admin/bin/console.out 发现了java程序没有跑起来,解决对应的bug问题即可,一般都是数据库连接的问题,可能和使用的数据库版…...
Redis 和 MySQL如何保证数据一致性
场景分析 Redis 用来实现应用和数据库之间读操作的缓存层,主要目的是减少数据库 IO ,还可以提升数据的 IO 性能。当应用程序需要去读取某个数据的时候,首先会先尝试去 Redis 里面加载,如果命中就 直接返回。如果没有命中…...
VR虚拟仿真技术在道路桥梁中有哪些具体应用?
虚拟现实(VR)是一种新兴的技术,可以为桥梁工程提供许多应用场景。以下是一些可能的应用场景: 1.桥梁设计和模拟 VR元宇宙可以用于桥梁的设计和模拟。工程师可以使用VR技术来创建桥梁的三维模型,并对其进行测试和优化。这可以帮助工程师更好地…...
如何找到死锁的线程?_java都学什么
在Java中,死锁是指两个或多个线程被无限地阻塞,等待彼此持有的资源,从而导致程序无法继续执行的情况。死锁通常是由于线程之间循环等待资源而产生的。要找到死锁的线程,可以采用以下方法: 1.线程转储(Thread Dump) 通过…...
MFC遍历目录包括子目录下所有文件、特定类型文件
文章目录 用法实现遍历所有文件遍历所有txt文件用法 vector<CString> v; //获取所有文件 GetFilePath(v,L"D:\\test\\"); //文件路径储存在容器里面,遍历容器 for(int i=0...
Kubernetes 集群calico网络故障排查思路
报错calico/node is not ready: BIRD is not ready: BGP not established with 172.16.0.20,172.16.0.30 \\calico未准备好,BGP协议不能与172.16.0.20,172.16.0.30内网IP地址连接 BGP协议:边界网关协议 访问k8s的dashboard界面无法访问网站,查看pod&am…...
OBS视频视频人物实时扣图方法(四种方式)
图片擦除一些杂乱图像 参考:https://www.bilibili.com/video/BV1va411G7be https://github.com/Sanster/lama-cleaner第一种:色度键选项 第二种:浏览器建立窗口选项 参考视频:https://www.bilibili.com/video/BV1WS4y1C7QY http…...
DROP USER c##xyt CASCADE > ORA-01940: 无法删除当前连接的用户
多创建了一个用户,想要给它删除掉 一 上执行过程,确实删除成功了 Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, OLAP, Advanced Analytics and Real Application Testing optionsSQL> DR…...
【JAVA】-【IO流】
文章目录 FileReader读入数据的基本操作FileReader中使用reader()FileWrite写出数据的操作使用FileInputStream、FileOutputStream操作图片缓冲流(字节型)实现非文本文件的复制 复制文本文件也可以使用字节流,但是不要在内存中读出来…...
PoseFormer:基于视频的2D-to-3D单人姿态估计
3D Human Pose Estimation with Spatial and Temporal Transformers论文解析 摘要1. 简介2. Related Works2.1 2D-to-3D Lifting HPE2.2 GNNs in 3D HPE2.3 Vision Transformers 3. Method3.1 Temporal Transformer Baseline3.2 PoseFormer: Spatial-Temporal TransformerSpati…...
Fortinet发布2023年第二季度财报
全球网络与安全融合领域领导者Fortinet(Nasdaq:FTNT),于近日公布2023年第二季度财报。 Fortinet 创始人、董事长兼首席执行官谢青表示:“作为业内领先的网络安全平台和安全组网厂商,得益于当下对整合型供应…...
智慧消防 | 气体灭火系统压力在线监测正当其时
气体灭火设备在消防安全系统中扮演着重要的角色。根据最新版的《气瓶安全技术规程》TSG23-2021规定,IG541气体钢瓶需要每3年进行一次检测。未按时进行检测可能导致压力掉压、瓶体外部锈蚀、钢瓶位置钢瓶内部腐蚀等风险,这些问题都可能对消防安全和效能产…...
并查集练习 — 扩展问题(二)
根据并查集练习 —岛屿数量的问题再次扩展: 原题是给定一个二维数组matrix(char[][]),里面的值不是1就是0,上、下、左、右相邻的1认为是一片岛。返回matrix中岛的数量。 扩展为:如果是中国的地图࿰…...
iTOP-i.MX8MM开发板添加 isb 转串口设备驱动
对于通过 USB 接口访问的模块,在 Linux 内核中集成 USB 驱动程序。我们需要配置内核选中支持 GSM 和 CDMA 模块的 USB 转串口驱动 > Device Drivers -> USB support (USB_SUPPORT [y]) -> USB Serial Converter support (USB_SERIAL [y]) -> USB dr…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
关于 ffmpeg设置摄像头报错“Could not set video options” 的解决方法
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/148515355 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...
Redis——Cluster配置
目录 分片 一、分片的本质与核心价值 二、分片实现方案对比 三、分片算法详解 1. 范围分片(顺序分片) 2. 哈希分片 3. 虚拟槽分片(Redis Cluster 方案) 四、Redis Cluster 分片实践要点 五、经典问题解析 C…...
【图片转AR场景】Tripo + Blender + Kivicube 实现图片转 AR 建模
总览 1.将 2D 图片转为立体建模 2. 3. 一、将 2D 图片转为立体建模 1.工具介绍 Tripo 网站 2.找图片 找的图片必须是看起来能够让 AI 有能力识别和推理的,因为现在的AI虽然可以补全但是能力还没有像人的想象力那么丰富。 比如上面这张图片,看起来虽…...
