每日三道面试题之 Java并发编程 (四)
1.什么是线程死锁
线程死锁是并发编程中一个常见问题,它发生在两个或多个线程永久性地阻塞彼此,等待对方释放锁,但没有任何一方先行释放锁的情况下。简单来说,每个线程都持有对方需要的资源而等待对方释放资源,导致所有相关线程都无法继续执行下去。
线程死锁通常涉及以下四个必要条件,这四个条件同时满足时,死锁就可能发生:
- 互斥条件:资源不能被多个线程同时共享,只能由一个线程在任一时刻使用。
- 至少有一个线程它必须持有一个资源且正在等待获取一个当前被其他线程持有的资源:即线程已经持有至少一个资源,但又试图获取另一个被其他线程持有的资源。
- 资源不能被线程(主动)抢占:线程已经获取的资源在未使用完之前,不能被其他线程强行抢占。
- 循环等待条件:发生死锁时,必然存在一个线程—资源的循环等待链,每个线程持有一个资源并等待下一个线程所持有的资源。
解决或避免死锁的方法通常包括:
- 破坏互斥条件:虽然对于某些资源(如打印机),这几乎不可能实现,但对于软件资源来说,可以通过允许某种程度的共享来实现。
- 破坏占有和等待条件:一种方法是要求线程一开始就请求所有必需资源,并且只有当所有请求都能被同时满足时,才分配给该线程。
- 破坏不可抢占条件:如果某线程获得了一部分资源但请求其他资源时被拒绝,那么它必须释放已占有的资源,稍后再重新尝试。
- 破坏循环等待条件:对所有资源进行排序,强制每个线程按顺序请求资源,这样就不会形成循环等待。
避免死锁的关键是对资源的访问进行仔细的控制和调度,以确保上述条件不会同时满足。
2.形成死锁的四个必要条件是什么
形成死锁的四个必要条件通常被称为死锁的四个基本条件,它们是:
-
互斥条件(Mutual Exclusion):资源不能被共享,只能由一个线程(或进程)在任一时刻使用。即在一段时间内某资源仅为一个线程所占用。如果此时还有其他线程请求该资源,则请求者只能等待,直到占有资源的线程释放该资源。
-
占有且等待条件(Hold and Wait):一个线程(或进程)至少保持一个资源,并且等待获取额外的资源,而这些额外的资源又被其他线程占有。线程因请求资源而阻塞时,对已获得的资源保持不放。
-
非抢占条件(No Preemption):资源不能被强行从一个线程(或进程)中夺走,线程(或进程)必须自愿释放资源。即一旦某线程已经获得了某资源,在未使用完之前,不能强行剥夺其资源。
-
循环等待条件(Circular Wait):存在一种线程(或进程)的等待循环,每个线程(或进程)都在等待下一个线程(或进程)所占有的资源。即在发生死锁时,必然存在一个线程—资源的环形链,链中的每一个线程(或进程)至少已经占有一个资源,又在等待获取下一个线程(或进程)已经占有的资源。
只有当这四个条件同时成立时,才会发生死锁。理解这些条件有助于在设计和开发软件时采取相应的预防和避免策略,从而减少或消除死锁的可能性。
3.如何避免线程死锁
避免线程死锁是多线程程序设计中的一个关键考虑点。虽然彻底避免死锁可能很困难,但以下策略可以显著减少发生死锁的风险:
-
避免一些必要条件:
- 互斥:对于一些资源(如打印机),互斥是必须的,但对于可共享的资源(如只读数据),可以通过允许多个线程共享资源来避免互斥。
- 持有并等待:要求线程在开始执行前请求所有必需的资源,并且只有当所有资源都可以被同时分配时,线程才能开始执行。这样做可以减少死锁,但可能会降低资源的利用率。
- 不可抢占:如果一个线程已经持有一些资源但请求其他资源失败,可以让它释放所有已持有的资源,从而允许其他线程使用它们,然后重新尝试。
- 循环等待:通过定义所有资源的线性顺序,并强制所有线程按此顺序请求资源,可以破坏循环等待条件。
-
使用锁超时:
- 在尝试获取锁时使用超时机制是一种避免死锁的实用方法。如果线程在指定时间内无法获取所有必需的锁,它会自动释放已经获取的锁并重新尝试。这种方法增加了死锁解除的可能性,但可能会引入性能问题。
-
死锁检测与恢复:
- 虽然这不是预防死锁的方法,但通过定期检查死锁的存在,并采取措施(如回滚某些操作或强制释放一些资源)来打破死锁,也是处理死锁问题的一种方式。
-
使用顺序锁定:
- 一种避免死锁的简单方法是在程序中对所有需要锁定的资源进行排序,并确保每个线程按照这一确定的顺序获取锁。这样做可以有效避免循环等待的条件。
-
减少锁的粒度:
- 使用更细粒度的锁或其他同步机制(如并发数据结构),可以减少锁的争用,从而减少死锁的可能性。但这也可能增加编程的复杂性。
-
使用非阻塞同步机制:
- 采用非阻塞的数据结构和算法,如使用原子变量和无锁编程技术,可以完全避免死锁。这些技术通过消除传统的锁机制,来确保线程间的同步。
通过综合应用以上策略,可以大大降低多线程应用程序发生死锁的风险。然而,完全避免死锁通常需要仔细的设计和深思熟虑的资源管理策略。
相关文章:
每日三道面试题之 Java并发编程 (四)
1.什么是线程死锁 线程死锁是并发编程中一个常见问题,它发生在两个或多个线程永久性地阻塞彼此,等待对方释放锁,但没有任何一方先行释放锁的情况下。简单来说,每个线程都持有对方需要的资源而等待对方释放资源,导致所…...

ubuntu20.04.6将虚拟机用户目录映射为磁盘Z
文章目录 linux虚拟机设置为NAT模式安装sshd服务映射目录到windows磁盘安装samba套件修改配置文件smb.conf重启smbd并设置用户名和密码 windows映射遇到的问题1、设置好之后映射不成功2、smbd下载失败3、smbd密码配置问题4、当有改动时候,最好重启一下smbd服务 linu…...

TCP挥手中TIME_WAIT存在的原因
四次挥手的一般过程如图所示: 在客户端收到FIN结束报文的时候不是立刻进入CLOSED状态,而是进入TIME_WAIT状态,一般等2MLS后进入关闭状态。 原因: 1.可靠地终止 TCP 连接。 2.保证让迟来的 TCP报文段有足够的时间被识别并丢弃。 …...

使用Docker部署jar包
vi DockerfileDockerfile内容 FROM java:8 ADD chery5G-admin.jar chery5G-admin.jar ENTRYPOINT ["java","-jar","chery5G-admin.jar"]上传jar包到Dockerfile文件同级目录 使用Dockerfile文件,将jar包制作为镜像 docker build -t…...
深入了解WebKit:结构简介
随着互联网的发展,网页浏览器已经成为我们日常生活中不可或缺的工具之一。而在众多浏览器中,WebKit引擎作为其中之一的重要角色,驱动着一系列流行的浏览器,例如Safari和一些移动端浏览器。那么,WebKit究竟是如何构建的…...
Pgsql怎样找到表中某个字段值重复的记录并删除冗余记录,只保留一条
背景 今天发现某个黄页爬取的数据有部分重复了,原本我用的公司详情页的url进行md5来作为主键做upsert入,但后面在核验数据时发现有些详情url虽是同一间公司的,但路由上有细微差别导致写入了重复的公司数据,所以要想办法清理掉重复…...
如何在HarmonyOS(鸿蒙操作系统)上进行应用开发
文章中提到的关键点包括: 学习ArkTS:作者建议初学者首先学习使用ArkTS编写Hello World程序,并可以通过TypeScript教程来快速掌握基础语法。对于有Flutter或React Native开发经验的开发者来说,页面布局会比较容易上手。 页面布局&…...
C++ typeid运算符介绍
在 C++ 中,typeid() 是一个运算符,用于获取表达式的类型信息。typeid() 运算符在 C++ 中是一个强大的工具,可以用于获取对象的类型信息、类型比较、多态类型判断、异常处理以及类型转换安全检查等场景中。 1. 类型比较: 可以使用 typeid() 来比较两个类型是否相同。 if …...

Android适配平板屏幕尺寸
一、划分手机和平板 人为判断方法: 大于6英寸的就是平板。小于6英寸的都是手机 平板尺寸: 6英寸、7英寸、10英寸、14英寸… Android系统支持多配置资源文件,我们可以追加新的资源目录到你的Android项目中。命名规范: 资源名字-限制符 l…...

汽车充电桩主板在出厂前需要做哪些检测?
充电桩主板作为核心组件承载着充电桩的关键功能,其性能和稳定性直接影响着用户充电体验、桩企产品合规和市场竞争力,以及主板厂商的品牌知名度。因此,对充电桩主板进行全面的测试尤为重要。 下面将详细介绍充电桩主板检测的内容,包…...

关于Renesas R7 的选项字节开关看门狗
Renesas看门狗的模式是在选项字节中进行配置的,OPBT0的寄存器说明如下, 关于看门狗模式 : 和看门狗喂狗方式: 我们选择关闭看门狗(也就是配置31位为软件触发看门狗开始,然后不启动就相当于关闭)…...
redis bigKey问题
bigKey的产生 1、使用String存储了大文件的二进制。 2、使用集合没有考虑到数据的规模,或者规模的增长。 3、哈希中冗余了大量键值对。 bigKey问题 1、操作大key时会阻塞线程:redis是单线程。 2、网络阻塞:在网络中占用大量网络流量。 …...

二手车商的套路
https://www.dongchedi.com/article/7126394624675578405 https://www.dongchedi.com/article/7126394624675578405 现在,有越来越多的人去了解二手车,二手车相对于新车来说,更加的亲民划算。很多新车需要四五十万,而二手车有可…...
c++ 根据ip主机号和子网掩码随机生成ip
在C中,可以使用以下方法根据给定的IP地址和子网掩码来随机生成IP地址。这里使用了库来生成随机数,以及<arpa/inet.h>库来处理IP地址。 #include <iostream> #include <random> #include <arpa/inet.h>std::string random_ip(co…...
事务的隔离级别
事务由哪些特性 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态…...
性能优化角度
1.启动角度 2.数据缓存角度比如历史信息联想 3.内存释放角度 4.配合并要求后端进行接口API整合 5.耗时较多需求,根据业务情况进行线程异步处理 6.通过开源的loop监控sdk日志埋点,可监控线程对应环路的休眠/唤醒时间间隔,优化卡顿 7.尽量避免离…...
Vue3 使用ElementUI 显示异常
element提供的样例不能正常显示,需要进行配置 1.npm install element-plus --save 2.main.js // main.ts import { createApp } from vue import ElementPlus from element-plus //全局引入 import element-plus/dist/index.css import App from ./App.vue const app = crea…...
从0开始复习python~
//,int() , abs(), divmod() ,float() ,complex() ,pow(), ** , bool() ,or , and , len() , range() , str() , 其中 for i in xxx: else: xxxxx; 有点意思... # 地板除,向下取整 print(-3//2) # 只保留整数部分 print(int(3.72)) # 绝对值 print…...

从零开始搭建后端信息管理系统(新手小白比如)
如果你是新手小白,首先我们要进行一些准备工作,安装一些基础软件, 备注一下:这里安装的vue环境的后台管理系统,不同的后台管理系统,需要安装不同的插件 准备工作: 安装 Visual Studio Code …...
CentOS 7详细介绍。
CentOS 7是CentOS项目发布的开源类服务器操作系统,自2014年7月7日正式发布以来,它已成为企业级Linux发行版本的佼佼者。CentOS 7不仅继承了其前身的优势,还在性能、安全性和易用性方面进行了显著的提升。以下是对CentOS 7的详细介绍。 一、C…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...