【JavaEE初阶】死锁问题

目录

 一、死锁的三种典型场景

1、一个线程,一把锁

2、两个线程,两把锁

3、N个线程,M把锁


死锁,是多线程代码中的一类经典问题。我们知道加锁是能解决线程安全问题的,但是如果加锁的方式不当,就可能产生死锁。

 一、死锁的三种典型场景

1、一个线程,一把锁

对于不可重入锁来说

一个线程没有释放锁, 然后又尝试再次加锁。
// 第一次加锁, 加锁成功
lock();
// 第二次加锁, 锁已经被占用, 阻塞等待.
lock();
按照之前对于锁的设定, 第二次加锁的时候, 就会阻塞等待. 直到第⼀次的锁被释放, 才能获取到第二个锁. 但是释放第⼀个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想干了, 也就无法进行解锁操作. 这时候就会死锁。

对于这种情况就是,如果锁是不可重入的锁,并且一个线程对这把锁加锁两次,就会出现死锁。

2、两个线程,两把锁

假设有两个线程,线程1获取到锁A(对A对象加锁),线程2获取到锁B(对B对象加锁),接下来,线程1尝试获取锁B,线程2尝试获取锁A,这时就会出现死锁。

示例代码如下:

public class ThreadDemo1 {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(()->{synchronized (A) {//sleep一下,让t2能拿到Btry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//在持有A的情况下,对B加锁synchronized (B) {System.out.println("t1拿到了两把锁");}}});Thread t2 = new Thread(()->{synchronized (B) {//sleep一下,让t1能拿到Atry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//在持有B的情况下,对A加锁synchronized (A) {System.out.println("t2拿到了两把锁");}}});//死锁,一直僵持着,若让t2先对A加锁,再对B加锁,就可避免死锁t1.start();t2.start();}
}

这时候发生死锁,线程就“卡住了”,无法继续工作(死锁属于程序中最严重的一类bug),可见这个代码不会运行出任何结果,如图:

我们可以通过 jconsole 来观察这两个线程此时的状态:

 

这两个线程都处于死锁阻塞的状态。

如果此时约定加锁顺序,让线程2也先对A加锁,后对B加锁,这样死锁就可以解决。

3、N个线程,M把锁

这里用一个典型的例子来描述,哲学家就餐问题。

哲学家就餐问题:该问题描述的是五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。

 

这个问题中,五个哲学家就相当于五个线程,五只筷子就相当于五把锁。

在绝大多数情况下,这个问题是可以正常工作的。但有一些极端的特殊情况,这时会产生死锁。假如同一时刻,所有的哲学家都想吃面条,同时拿起了自己左边的筷子,这个时候,他们继续尝试拿起右边的筷子,这时就拿不到了,因为被别人给拿着了。此时,哲学家们都等待旁边的人释放筷子,但由于所有的哲学家都不想放下自己手中的筷子,这时就产生死锁了,谁都吃不到面条。

如何解决死锁呢?我们先来看一下产生死锁的四个必要条件

  • 互斥使用:获取锁的过程是互斥的,一个线程拿到了这把锁,另一个线程也想获取,就要阻塞等待。
  • 不可抢占:一个线程拿到这把锁后,只能主动解锁,不能让别的线程强行把锁抢走。
  • 请求保持:一个线程拿到了一把锁后,会持有这把锁,像持有锁A的情况下,尝试获取锁B。
  • 循环等待/环路等待:像哲学家问题一样,1号哲学家等待2号哲学家释放筷子,2号哲学家等待3号哲学家释放筷子……

解决死锁的问题,核心思路就是破坏上述的必要条件,只要破坏一个就可以解决死锁。

对于互斥使用和不可抢占,这是锁的最基本特性,不太好破坏;对于请求保持(代码结构方面),是否能破坏,要看实际需求;对于循环等待(代码结构方面),是最容易破坏的。

解决上述哲学家问题死锁的情况,其实有很多方案:

  1. 引入额外的筷子
  2. 去掉一个线程(哲学家)
  3. 引入计数器,限制最多同时有几个哲学家进餐
  4. 引入加锁顺序的规则
  5. 银行家算法(操作系统中的重要内容)

 1、2、3方案,虽然不复杂,但是普适性不高,有时候用不了;3方案普适性高。

我们这里用一下3方案(引入加锁顺序的规则)来解决哲学家死锁的问题,只要指定一定的规则,就可以有效避免循环等待,从而破坏循环等待这个必要条件指定加锁顺序,针对五只筷子,进行编号,约定每个哲学家获取筷子的时候,一定要先拿自己左右两边编号较小的筷子,拿到之后,再拿编号较大的。如图(假设2号哲学家先拿到1号筷子):

 

5号哲学家拿到5号筷子后,就可以进餐了,吃完之后,放下4号和5号筷子;接着,4号哲学家就可以拿到4号筷子,进餐,吃完之后,放下3号和4号筷子;接着,3号哲学家就可以拿到3号筷子,进餐,吃完之后,放下2号和3号筷子……最终,1号哲学家就可以拿到1号筷子和5号筷子,进餐。这样每个哲学家都可以吃到面条,死锁问题也就解决了。

 

 

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

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

相关文章

工会排队奖励模式:创新营销策略,实现共赢局面

在当今的商业环境中,创新营销策略的重要性日益凸显。工会排队奖励模式作为一种新型的营销策略,旨在通过结合线上和线下消费,激励消费者购买产品或服务,并获得返现奖励。这种模式通过将消费者的支出和商家的抽成资金纳入奖金池&…

CH58x-BLE 程序阅读笔记

CH58x-BLE 程序阅读笔记 1. 广播1.1 广播类型设置1.2 广播数据长度 2. MTU设置2.1 CH58x 蓝牙协议栈支持有效最大MTU为247 1. 广播 1.1 广播类型设置 1.2 广播数据长度 1) GAP-广播数据(最大大小31字节,但最好保持较短以节省广告时的电量&a…

python tkinter 使用(十一)

python tkinter 使用(十一) #!/usr/bin/python3 # -*- coding: UTF-8 -*- """Author: zhTime 2023/11/27 下午3:36 .Email: Describe: """ import tkinter from tkinter import *master Tk() master.title("菜单") master.geometry…

记录MySql删除42亿行数据表方法

背景: 现网db有个log表自增ID溢出,业务已经切换到其他表,但是之前有其他业务删除大表导致现网出现故障,这里考虑到是一张静态表,所以采用的是直接删除的方式,记录下当时的删除的步骤。 直接删除的风险&am…

Linux 磁盘挂载

一、查看挂载点 df -h 二、查看磁盘信息 fdisk -l 下面红色的这一块就是未分区的磁盘 三、 进行磁盘分区 fdisk /dev/sdb /dev/sdb :是上面fdisk -l查询出来未分区的磁盘地址 根据提示输入m获取命令 四、执行命令,创建一个分区 1、新建分区&#…

【前端】three.js

文章目录 概述three.js-master目录结构Threejs 的基本要素场景相机透视相机正交相机 网格2d3d 灯光AmbientLight(环境光)平行光(DirectionalLight)点光源(PointLight)聚光灯(SpotLight) 渲染器 Threejs 的实…

WordPress更改文章分类插件

当WP网站内容比较多的时候,有时候如果涉及到批量修改文章分类,如果一个个的去操作的话就太费事了,如果使用后台批量修改分类的话是增加旧分类不会取消选择,就就导致我们适得其反还需要一个一个的去编辑取消,实在繁琐了…

Java高级技术(单元测试)

一,概括 二,junit 三,案例 (1),实验类 package com.bilibili;public class Name {public static void main(String name) {if (name null){System.out.println("0");return;}System.out.print…

PC端数据列表有头像显示头像,没有头像显示名字的第一个字

PC端数据列表有头像显示头像&#xff0c;没有头像显示名字的第一个字 .charAt(0) 是 JavaScript 字符串对象的方法&#xff0c;用于获取字符串的第一个字符。 字符串中的字符位置是从 0 开始的&#xff0c;所以.charAt(0) 就表示获取字符串的第一个字符。 <el-table ref&qu…

哈希思想应用【C++】(位图,布隆过滤器,海量数据处理面试题)

目录 一&#xff0c;位图 1. 位图概念 2.实现 3. 测试题 位图的优缺点 二&#xff0c;布隆过滤器 1). 布隆过滤器提出 2). 概念 3). 布隆过滤器的查找 4). 布隆过滤器删除(了解) 5). 布隆过滤器优点 6). 布隆过滤器缺陷 三&#xff0c;海量数据面试题 1&#xff…

java开发必备的Tomcat-servlet-http和spring boot基础入门

tomcat 介绍 概念&#xff1a; Tomcat是一个开源免费的轻量级Web服务器&#xff0c;是Apache软件基金会的核心项目&#xff0c;支持Servlet/JSP少量JavaEE(JakartaEE)规范。 JavaEE&#xff1a;Java Enterprise Edition&#xff0c;Java企业版。指Java企业级开发的技术规范总和…

Arduino驱动DHT20温湿度传感器(温湿度传感器)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 DHT20温湿度传感器是DHT11的全新升级版。 DHT20采用全新的ASIC专用芯片、改进的MEMS半导体电容式湿度传感器元件和标准片上温度元件。所有传感器均经过工厂校准,具有低功耗、高精度和稳定性、响应…

Testlink 1.9.20+phpstudy_pro安装遇到的问题

phpstudy_pro启动了Apache2.4.39和Mysql5.7.26,php的版本是7.3.4zai。 安装Testlink 1.9.19时没有数据库的问题&#xff0c;安装Testlink 1.9.20时遇到了数据库问题&#xff0c;如下图所示&#xff1a; 网上搜索“Failed!Mysql Database cannnot be used”&#xff0c;给出的…

【笔记+代码】JDK动态代理理解

代码地址 https://github.com/cmdch2017/JDKproxy.git/ 我的理解 我的理解是本身service-serviceImpl结构&#xff0c;新增一个代理对象proxy&#xff0c;代理对象去直接访问serviceImpl&#xff0c;在proxy进行事务的增强操作&#xff0c;所以代理对象实现了接口。如何实现…

STM32开发学习(地址映射)

LED灯代码&#xff1a; #define PERIPH_BASE ((unsigned int)0x40000000)#define AHB1PERIPH_BASE (PERIPH_BASE 0x00020000)#define GPIOF_BASE (AHB1PERIPH_BASE 0x1400)#define GPIOF_MODER *(unsigned int*)(GPIOF_BASE0x00) #define GPIOF_BSRR *(uns…

如何批量群发邮件

批量群发邮件的方法有多种&#xff0c;以下列举几种常见的方式&#xff1a; 使用专业的邮件营销平台&#xff1a;通过专业的邮件营销平台&#xff0c;如一米软件、米贸搜等&#xff0c;可以一次性向多个收件人发送邮件。这些平台通常具有强大的邮件发送和管理功能&#xff0c;…

Linux下Docker 离线安装详细步骤,亲测成功

1.离线原因&#xff1a;公司新创不能使用开元linux&#xff0c;使用了一个变种centOS&#xff0c;致使yum被禁 2.步骤&#xff1a; 2.1 下载docker tar包&#xff0c;下载地址&#xff1a;Index of linux/https://download.docker.com/linux/ 2.2 新建自己的软件目录&am…

大数据之HBase

HBase介绍 Apache的三篇论文&#xff0c;GFS谷歌文件系统->HDFS&#xff1b;MR -> MR ; BigTable ->HBase;HBase是hadoop数据库&#xff0c;一种分布式、可扩展的大数据NoSQL数据库之一。适合对于大量数据进行随机、实时的读写操作 HBase数据模型 Bigtable是一个稀…

It was migrated from homebrew/core to homebrew/cask.

给mac配置安卓环境时报错&#xff1a; brew install android-platform-tools Warning: No available formula with the name "android-platform-tools". > Searching for similarly named formulae... Error: No similarly named formulae found. It was migrate…

时区处理综述(java技术栈)

文章目录 一、jdbc协议对时间的序列化(不含时区信息)数据库的两个时间类型中国数据库使用的CST时区无法被java正确识别jdbc协议跨时区传输方案 二、数字时间戳(可跨时区传输)定义用途 三、ISO8601(可跨时区传输)java的序列化方法js的序列化方法 四、解析时间字符串(不含时区信息…