java死锁的成因和解决方案

一、什么是死锁? 

在Java中,死锁是指两个或多个线程互相持有对方所需要的锁,并且在无法继续执行的情况下永久地等待对方释放锁。这种情况下,所有涉及的线程都无法继续执行,程序被卡住,无法正常终止。

死锁通常发生在多线程并发执行时,当线程之间相互竞争获取资源的时候。典型的死锁场景包括以下四个条件的同时满足:

  1. 互斥:至少有一个资源同时只能被一个线程占用;
  2. 占有并等待:一个线程已经占有一个资源,同时还等待另一个线程占有的资源;
  3. 不可剥夺:一个线程已经占有的资源不能被其他线程强制性剥夺;
  4. 环路等待:多个线程之间形成等待资源的环路。

当这四个条件同时满足时,就会导致死锁的发生。为了避免死锁,可以采取一些预防措施,例如合理地设计资源分配顺序、避免线程持有多个锁、使用定时锁等待等方法来减少死锁的风险。

 

二、产生死锁的三个典型场景 

1、一个线程一把锁

如果一个线程对同一把锁,连续加了两次锁,就会产生死锁。当然如果锁是可重入锁则不会死锁,可重入锁,字面意思是“可以重新进入的锁”,即允许同一个线程多次获取同一把锁,不会出现死锁的情况。(每次线程拿锁的时候,都会判断一下这个锁的已拥有者有没有这个线程,如果有则会放行,因此就不会出现一个线程连续加了两次锁,也就不会死锁)

解决方案:

无脑使用synchronized,因为它是可重入锁。 

2、两个线程两把锁

public class demo2 {

    public static void main(String[] args) {
        Object locker1 = new Object();
        Object locker2 = new Object();    
        Thread t1 = new Thread(() -> { 
            synchronized (locker1) {
                synchronized (locker2) {
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            synchronized (locker2) {
                   synchronized (locker1) {

                }
            }
        });
        t2.start();
    }

死锁原因:线程t1拿到锁1,线程t2拿到锁2。接着线程t1想要锁2,但此时锁2被线程t2占用着,t1无法获取,陷入阻塞等待,而t2想要锁1,但锁1被t1占用着。就这样t1和t2陷入僵局,谁也无法正常释放锁,从而形成了死锁。

解决办法

线程t1与线程t2的加锁顺序一样即可:

public class demo2 {

    public static void main(String[] args) {
        Object locker1 = new Object();
        Object locker2 = new Object();    
        Thread t1 = new Thread(() -> { 
            synchronized (locker1) {
                synchronized (locker2) {
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            synchronized (locker1) {
                   synchronized (locker2) {

                }
            }
        });
        t2.start();
    }

3、N个线程M把锁 

哲学家问题:

哲学家问题是计算机科学领域中的一个经典问题,它用来探讨在并发编程中可能出现的资源竞争和死锁问题。这个问题通常用于说明多线程和并发编程中的困难和挑战。

问题的设定是这样的:有一圈圆桌上有一些哲学家,每个哲学家面前放有一个盘子,圆桌上有一些餐叉,每两个相邻的哲学家之间有一把餐叉。哲学家的生活有两种状态:思考和进餐。当哲学家思考时,他们不需要任何资源,但当他们饿了的时候,他们会试图拿起左右两边的餐叉,如果两把餐叉都可用,他们就可以进餐,进餐完毕后,他们会放下餐叉继续思考。

问题的关键在于如何协调哲学家之间的行为,以避免死锁(所有哲学家都拿起一只餐叉,等待另一只,导致无法继续进餐)和资源竞争(多个哲学家同时试图拿起同一把餐叉,导致冲突)。

解决这个问题的方法包括使用各种同步机制,如互斥锁、信号量等,以确保哲学家在进餐时能够安全地占用需要的资源,避免发生死锁和资源竞争。

哲学家问题在并发编程中是一个经典的例子,用来说明如何有效地管理共享资源,以防止出现一些常见的并发问题。

 解决办法

这个问题有很多方法的,其中一个方法是我们规定其中一个人等其他人都吃完了才可以拿筷子。按照这样的思路,这个死锁问题就可以得到解决。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Question 1----dlib问题

复现代码时,在环境里边导入dlib包时一直出现setup.py运行失败,查找网上一些解决方法,使用whl文件本地导入 仍然不能解决,通过向师兄请教,成功解决问题。 首先需要先安装两个库:(已经安装好了VS…

pyside/qt03——人机协同的编程教学—直接面向chatGPT实战开发(做中学,事上练)

先大概有个草图框架,一点点丰富 我纠结好久,直接用Python写UI代码 还是用designer做UI 再转Python呢, 因为不管怎么样都要转成Python代码, 想了想还是学一下designer吧,有个中介,有直观理解。 直接这样也可…

“福利”还是“陷阱”?公司给员工放假3个月引发劳动权益争议

近日,广东佛山一家玻璃制造公司的长达3个月放假通知引发广泛关注。这一决策引发了社会对员工福利和公司经营平衡的深入思考。公司表示,此次决策是为了维修老化设备,但随之而来的疑虑则主要集中在员工的收入和劳动权益问题上。 公司表示&…

Java线程池—附阿里巴巴Java开发手册强制规范要求

文章目录 一、线程池概述二、创建线程池三、线程池执行Runnable任务四、线程池执行Callable任务五、线程池工具类(Executors)—不推荐 一、线程池概述 线程池就是一个可以复用线程的技术。 想象一下,如果不使用线程池会有什么问题&#xff1…

spring IOC介绍

spring的Ioc真是个好东西啊,那它到底是什么东西呢,控制反转,到底是怎么转的呢? 假设啊你现在是一个导演,想排部戏,那是不是得需要演员和舞台(spring中的bean),如果按平常的编程思维就是new 一个…

女装品牌网站建设的作用如何

服装是任何人都需要的必备品,尤其是女装,由于女性群体爱美追求时尚的心理更高,因此市场中有大量女装品牌以及大量消费者,其规模非常高,众多大小品牌林立及消费征集下,商家们经营也并不太容易,企…

YouTube网红营销:出海品牌扩大影响力的关键

随着数字媒体的兴起,社交媒体已成为品牌与消费者之间建立联系的重要桥梁。其中,YouTube作为全球最大的视频分享平台,不仅拥有庞大的用户群体,还聚集了众多有影响力的网红。这些网红在各自的领域内拥有强大的话语权和号召力&#x…

区块链实验室(28) - 拜占庭节点劫持区块链仿真

在以前的FISCO环境中仿真拜占庭节点攻击区块链网络。该环境共有100个节点,采用PBFT作为共识机制,节点编号分别为:Node0,Node,… ,Node99。这100个节点的前2010区块完全相同,自区块2011开始分叉。…

No suitable driver found for jdbc:mysql://localhost:3306(2023/12/7更新)

有两种情况: 压根没安装下载了但没设为库或方法不对 大多数为第一种情况: 一. 下载jdbc 打开网址选择一个版本进行下载 https://nowjava.com/jar/version/mysql/mysql-connector-java.html 二.安装jdbc 在项目里建一个lib文件夹 在把之前下载的jar文…

【开源】基于Vue+SpringBoot的陕西非物质文化遗产网站

文末获取源码,项目编号: S 065 。 \color{red}{文末获取源码,项目编号:S065。} 文末获取源码,项目编号:S065。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 设计目标2.2 研究内容2.3 研究方法与…

四十一、高可用

一、定义 TC(Tencent Cloud)的异地多机房容灾架构是指,在不同的地理位置上配置多个数据中心,以确保系统的高可用性和容灾能力。当某个数据中心发生故障或者不可用时,可以自动切换到其他数据中心来提供服务,…

vscode如何为python设置静态类型检测工具:mypy

设置好之后的效果如下图所示,你可以在下方problems一栏看到工作区所有文件存在的问题 安装mypy就像其他插件一样,在extensions中搜索mypy,再install即可。 但是安装以后,我的vscode弹出了以下通知: The mypy daemon e…

Global IIIumination(GI)全局光照原理(一)3D空间全局光照

文章目录 一、Global IIIumination(GI)全局光照基本概念二、主流的全局光照方法:三、Reflective shadow maps(RSM)反射阴影贴图 全局光照四、Light Propagation Volumes (LPV)光线传播体积 全局光照1.第一步&#xff0…

Linux中的网络时间服务器

本章主要介绍网络时间的服务器 使用chrony配置时间服务器配置chrony客户端服务器同步时间 1.1 时间同步的重要性 一些服务对时间要求非常严格,例如如图所示的由三台服务器搭建的ceph集群 这三台服务器的时间必须保持一致,如果不一致,就会显…

C语言之动态内存管理(malloc calloc realloc)

C语言之动态内存管理 文章目录 C语言之动态内存管理1. 为什么要有动态内存管理2. malloc 和 free2.1 malloc2.2 free2.3 例子 3. calloc 和 realloc3.1 calloc3.2 realloc 4. 常见的动态内存错误4.1 对NULL指针的解引⽤操作4.2 对动态开辟空间的越界访问4.3 对⾮动态开辟内存使…

Themis: Fast, Strong Order-Fairness in Byzantine Consensus

目录 笔记后续的研究方向摘要引言秩序井然 Themis: Fast, Strong Order-Fairness in Byzantine Consensus CCS 2023 笔记 后续的研究方向 摘要 我们介绍了Themis,这是一种将交易的公平排序引入(许可的)拜占庭共识协议的方案,最…

【洛谷】更换头像

错误展示 今天换头像的时候发现一直换不了,即使显示修改成功,然后我等了半个多小时也还没换好 解决办法 上传成功头像后,按ctrl F5 结果 更新成功!

文本润色工具有哪些,高质量的文本润色软件

在当今信息过载的时代,文本的重要性愈发凸显。即便是最精心构思的文章,若未经过仔细的润色,也难以达到最佳的表达效果。本文将专心分享文本润色工具的种类。 文本润色工具的种类 文本润色工具根据其功能和应用范围可以分为多个种类&#xff…

菜鸟学习日记(python)——推导式

python中的推导式是一种独特的数据处理方式,可以从一个数据序列去构建另一个新的数据序列的结构体。 它包括以下推导式: 列表(list)推导式字典(dict)推导式集合(set)推导式元组&am…

Kettle 安装配置

文章目录 Kettle 安装配置Kettle 安装Kettle 配置连接 Hive Kettle 安装配置 Kettle 安装 在安装Kettle之前,需要确定已经安装Java运行环境。Kettle需要Java的支持才能运行,JDK的版本最好是8.x的太新的也会出现bug。Kettle的7.1版本的太旧了&#xff0…