【JavaEE】多线程 -- 死锁问题

目录

1. 问题引入

2.死锁问题的概念和原因

 3. 解决死锁问题


1. 问题引入

在学习死锁之前, 我们先观察下面的代码能否输出正确的结果:

运行程序, 能正常输出结果:

这个代码只管上看起来, 好像是有锁冲突的, 此时的 locker 对象已经是加锁的状态, 在尝试对 locker 加锁, 不应该会出现阻塞问题吗?

其实, 问题的关键是,这两次加锁, 其实是在同一个线程上进行的.  由于是同一个线程, 此时锁对象就知道了第二次加锁的线程,  第二次加锁操作就可以直接放行通过, 不会出现阻塞.  这个特性称为 "可重入". 

使用可重入锁, 可以避免代码出现死锁问题, 如果使用的不是可重入锁, 就会出现死锁问题.

2.死锁问题的概念和原因

Java多线程中的死锁问题是指两个或多个线程互相持有对方所需的资源而无法继续执行的情况。这种情况下,线程无法释放已经占有的资源,也无法获取自己所需的资源,导致程序无法继续执行下去。

通常,发生死锁问题需要满足以下四个条件:

  1. 互斥条件(Mutual exclusion):至少有一个资源同时只能被一个线程占用。
  2. 请求与保持条件(Hold and wait):线程至少已经占有一个资源,并且正在请求另一个被其他线程占用的资源。
  3. 不可剥夺条件(No preemption):已经分配给一个线程的资源不能被强制剥夺。
  4. 循环等待条件(Circular wait):存在一个线程链,每个线程都在等待下一个线程所占有的资源。

死锁的例子:

线程1获取到锁A, 线程2获取到锁B, 接下来, 线程1尝试获取锁 B, 线程2尝试获取锁A, 此时出现了死锁问题:  

package thread;

public class ThreadDemo22 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()-> {
           synchronized (A) {
               // sleep 是为了t2时间, 让t2也能拿到 B
               try {
                   Thread.sleep(1000);
               }catch (InterruptedException e) {
                   e.printStackTrace();
               }

               //尝试获取B, 并没有释放 A
               synchronized (B) {
                   System.out.println("t1拿到了两把锁");
               }
           }
        });

        Thread t2 = new Thread(()->{
            synchronized (B) {
                // sleep 是给t1时间, 让t1能拿到 A
                try {
                    Thread.sleep(1000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //尝试获取A, 并没有释放 B
                synchronized (A) {
                    System.out.println("t2拿到了两把锁");
                }
            }
        });

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

 程序没有任何输出结果:

 3. 解决死锁问题

为了避免死锁问题,可以采取以下策略:

  1. 避免使用多个锁:尽量减少使用多个锁,如果必须使用多个锁,确保获取锁的顺序是一致的,以减少死锁的可能性。
  2. 加锁顺序:多个线程获取锁的顺序要保持一致,避免出现循环等待条件。
  3. 加锁时限:在获取锁的时候设置超时时间,如果一段时间内没有获取到锁,就放弃当前的操作,释放已经持有的锁,避免长时间等待导致死锁。
  4. 死锁检测:通过监控线程的状态和资源的使用情况,及时检测并解决潜在的死锁问题。

对于死锁例子, 我们可以使两个线程的取锁顺序保持一致:

package thread;

public class ThreadDemo22 {
    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(()-> {
           synchronized (A) {
               // sleep 是为了t2时间, 让t2也能拿到 B
               try {
                   Thread.sleep(1000);
               }catch (InterruptedException e) {
                   e.printStackTrace();
               }

               //尝试获取B, 并没有释放 A
               synchronized (B) {
                   System.out.println("t1拿到了两把锁");
               }
           }
        });

        Thread t2 = new Thread(()->{
            synchronized (A) {
                // sleep 是给t1时间, 让t1能拿到 A
                try {
                    Thread.sleep(1000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //尝试获取A, 并没有释放 B
                synchronized (B) {
                    System.out.println("t2拿到了两把锁");
                }
            }
        });

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

 

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

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

相关文章

鸿蒙HarmonyOS应用开发-ColumnRow组件

1 概述 一个丰富的页面需要很多组件组成,那么,我们如何才能让这些组件有条不紊地在页面上布局呢?这就需要借助容器组件来实现。 容器组件是一种比较特殊的组件,它可以包含其他的组件,而且按照一定的规律布局&#xf…

【docker系列】docker实战之部署SpringBoot项目

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

js提取iconfont项目的图标

iconfont 可以让我们轻松使用字体图标,比如使用 iconfont 提供的 js,就可以愉快的码代码了。 //at.alicdn.com/t/c/font_xxxxx.js通常公司会有提供一套图标供所有系统使用,比如图标库里有 1000 个图标,但某个项目只需要使用 10 个…

南大通用 GBase 8s数据库级别权限

对于所有有权使用指定数据库的用户都必须赋予其数据库级别的用户权限。在GBase 8s 中,数据库级别的用户权限有三种,按权限从低到高排列依次为:CONNECT、RESOURCE、DBA。 1. CONNECT 这是级别最低的一种数据库级别用户权限。拥有该权限的用户…

Windows Terminal CMD 终端配置方案: 不只是酷炫外观

大一的时候小学期我们还是用 Windows cmd 终端写的订餐系统,尽管进我们所能地改了改配色,成品还是让人不忍直视。 当时学习遇到的大多数运行需求可以通过 IDE 解决,再加上 CMD 丑成这样,挺让人抵触的。 后来对命令行操作的学习需…

【数据清洗 | 数据规约】数据类别型数据 编码最佳实践,确定不来看看?

🤵‍♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…

回文链表,剑指offer 27,力扣 61

目录 题目: 我们直接看题解吧: 解题方法: 难度分析: 审题目事例提示: 解题分析: 解题思路(数组列表双指针): 代码说明补充: 代码实现: 代码实现&a…

Pix2Pix 使用指南:一副图像到另一副图像的转换

Pix2Pix Pix2Pix 介绍:使用条件 GAN 进行图像到图像的转换Pix2Pix 原理Pix2Pix 模型结构生成器:Unet结构判别器:PatchGAN目标函数目标函数总结 Pix2Pix 项目使用 Pix2Pix 介绍:使用条件 GAN 进行图像到图像的转换 Pix2Pix 论文&a…

第十八章,Swing窗体

概述 String包的层次结构和继承关系如下 常用的Swing组件如下表 Swing常用窗体 JFrame 窗体 JFrame 类的常用构造方法包括以下两种形式: public JFrame():创建一个初始不可见、没有标题的窗体。 public JFrame(String title)&a…

网络基础『发展 ‖ 协议 ‖ 传输 ‖ 地址』

🔭个人主页: 北 海 🛜所属专栏: 神奇的网络世界 💻操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌤️前言🌦️正文1.网络发展1.1.背景1.2.类型 2.网络协议2.1.什么是协议2.2.协议…

Bilateral Guided Upsampling

Abstract 我们提出了一种加速一大类图像处理算子的算法。给定低分辨率参考输入和输出对,我们通过拟合将输入映射到输出的局部曲线来对算子进行建模。然后,我们可以通过在全分辨率输入上评估这些低分辨率曲线来生成全分辨率输出。我们证明,这…

经典策略梯度算法

经典策略梯度算法 DDPG算法 DDPG 算法被提出的初衷其实是 DQN 算法的一个连续动作空间版本扩展。深度确定性策略梯度算法( deep deterministic policy gradient,DDPG),是一种确定性的策略梯度算法。 由于DQN算法中动作是通过贪…

DCDC前馈电容与RC串并联电路

一、RC串并联电路特性分析 1、RC串联电路 RC 串联的转折频率: f01/(2πR1C1),当输入信号频率大于 f0 时,整个 RC 串联电路总的阻抗基本不变了,其大小等于 R1。 2、RC并联电路 RC 并联电路的转折频率&…

学习笔记三十六:通过Ingress-nginx实现灰度发布

通过Ingress-nginx实现灰度发布 灰度发布原理将新版本灰度给部分用户切一定比例的流量给新版本 部署两个版本的服务以 nginx 为例,先部署一个 v1 版本:部署一个 v2 版本再创建一个 Ingress,对外暴露服务,指向 v1 版本的服务:访问验证 基于 He…

csdn最新最全面的Jmeter接口测试:jmeter_逻辑控制器_循环控制器

循环控制器 循环次数:设置该控制器下的请求的循环执行次数 永远:勾选上的话,会一直循环,即所谓死循环 注意:如果线程组本身已经设置了循环次数的话,那循环控制元件控制的子节点 的循环次数为线程组设置的…

高级IO select 多路转接实现思路

文章目录 select 函数fd_set 类型timeval 结构体select 函数的基本使用流程文件描述符就绪条件以select函数为中心实现多路转接的思路select 缺陷 select 函数 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); selec…

科普:什么是合同生命周期管理?

在当前,企业面临自身转型升级与行业数字建设的挑战,急需一种系统化的解决方案,帮助企业在自身运作方面实现降本增效,为拓展业务获得发展提供助力,而合同生命周期管理在其中就扮演着十分重要的角色。 一、合同生命周期…

解读《陆奇最新演讲实录—我的大模型世界观》

腾讯科技频道记者张小珺一篇《陆奇最新演讲实录—我的大模型世界观》刷爆朋友圈。文章知识点丰富、字里行间处处流淌着创业方法论和AI应用商机,含金量极高! PS:一家之言、不求苟同。如有不爽之处,欢迎来 找我。 腾讯新闻原文&am…

宝塔mongodb启动失败

宝塔mongodb启动失败 尝试以下步骤: 命令行启动看报错信息 /etc/init.d/mongodb start出现 error:14,查看 mongodb.log 提示 MongoDB –无法解除套接字文件 /tmp/mongodb-27017 的链接 查看 /tmp/mongodb-27017.sock,发现拥有…

STM32CubeIDE(CUBE-MX)----快速移植FreeRTOS实战

文章目录 前言一、Freertos可视化配置二、生成代码三、实验现象总结 前言 FreeRTOS(Real-Time Operating System)是一个开源的实时操作系统内核,专注于嵌入式系统。它提供了一套用于管理任务、调度器、内存管理等的实时操作系统功能&#xf…