线程死锁

线程池自引发死锁 线程池自引发死锁 死锁是由许多线程锁定相同资源引起的 如果在该池中运行的任务内使用线程池,也会发生死锁 像RxJava / Reactor这样的现代图书馆也很容易受到影响 死锁是两个或多个线程正在等待彼此获取的资源的情况。例如,线程A等待lock1线程B锁定,而线程B等待lock2,由线程A锁定。在最坏的情况下,应用程序冻结无限期的时间。让我向您展示一个具体的例子。想象一下,有一个Lumberjack类可以保存对两个附件锁的引用: import com.google.common.colle 阅读详情

一、死锁

      何为死锁,用一个进餐场景来描述,一桌子饭,5个人吃,5根筷子,每人面前一根,假如刚好有一种算法是每个人立即拿起一根筷子,同时又等待你右侧的人放下筷子,你成一双,然后吃饭,这样大家都会饿死,这就解释了死锁的现象。两个线程死锁也是同样的道理,线程A持有M锁,而等待L锁释放,线程B持有L锁,但等待M锁释放,于是就发生了死锁。

1.1、顺序死锁

	public class LeftRightDeadlock {
		    private final Object left = new Object();
		    private final Object right = new Object();

		    public void leftRight() {
		        // 得到left锁
		        synchronized (left) {
		            // 得到right锁
		            synchronized (right) {
		                doSomething();
		            }
		        }
		    }

		    public void rightLeft() {
		        // 得到right锁
		        synchronized (right) {
		            // 得到left锁
		            synchronized (left) {
		                doSomethingElse();
		            }
		        }
		    }
		}

 

  • 线程A调用leftRight()方法,得到left锁
  • 同时线程B调用rightLeft()方法,得到right锁
  • 线程A和线程B都继续执行,此时线程A需要right锁才能继续往下执行。此时线程B需要left锁才能继续往下执行。
  • 但是:线程A的left锁并没有释放,线程B的right锁也没有释放。
  • 所以他们都只能等待,而这种等待是无期限的-->永久等待-->死锁

1.2动态锁顺序死锁

public static void transferMoney(Account fromAccount,
                Account toAccount,
                DollarAmount amount)
                        throws InsufficientFundsException {

            // 锁定汇账账户
            synchronized (fromAccount) {
                // 锁定来账账户
                synchronized (toAccount) {

                    // 判余额是否大于0
                    if (fromAccount.getBalance().compareTo(amount) < 0) {
                            throw new InsufficientFundsException();
                    } else {

                            // 汇账账户减钱
                        fromAccount.debit(amount);

                            // 来账账户增钱
                        toAccount.credit(amount);
                    }
                }

}

 

  • 如果两个线程同时调用transferMoney()
  • 线程A从X账户向Y账户转账
  • 线程B从账户Y向账户X转账
  • 那么就会发生死锁。
  • A:transferMoney(myAccount,yourAccount,10);
    
    B:transferMoney(yourAccount,myAccount,20);

 

1.3协作对象之间发生死锁

public class CooperatingDeadlock {
    // Warning: deadlock-prone!
    class Taxi {
        @GuardedBy("this") private Point location, destination;
        private final Dispatcher dispatcher;

        public Taxi(Dispatcher dispatcher) {
            this.dispatcher = dispatcher;
        }

        public synchronized Point getLocation() {
            return location;
        }

        // setLocation 需要Taxi内置锁
        public synchronized void setLocation(Point location) {
            this.location = location;
            if (location.equals(destination))
                // 调用notifyAvailable()需要Dispatcher内置锁
                dispatcher.notifyAvailable(this);
        }

        public synchronized Point getDestination() {
            return destination;
        }

        public synchronized void setDestination(Point destination) {
            this.destination = destination;
        }
    }

    class Dispatcher {
        @GuardedBy("this") private final Set<Taxi> taxis;
        @GuardedBy("this") private final Set<Taxi> availableTaxis;

        public Dispatcher() {
            taxis = new HashSet<Taxi>();
            availableTaxis = new HashSet<Taxi>();
        }

        public synchronized void notifyAvailable(Taxi taxi) {
            availableTaxis.add(taxi);
        }

        // 调用getImage()需要Dispatcher内置锁
        public synchronized Image getImage() {
            Image image = new Image();
            for (Taxi t : taxis)
                // 调用getLocation()需要Taxi内置锁
                image.drawMarker(t.getLocation());
            return image;
        }
    }

    class Image {
        public void drawMarker(Point p) {
        }
    }
}

 

  • 并且在操作途中是没有释放锁的

这就是隐式获取两个锁(对象之间协作)..

这种方式也很容易就造成死锁.....

二、避免死锁的方法

  • 固定加锁的顺序(针对锁顺序死锁)
  • 开放调用(针对对象之间协作造成的死锁)
  • 使用定时锁-->tryLock()

2.4死锁检测

JDK提供了两种方式来给我们检测:

  • JconsoleJDK自带的图形化界面工具,使用JDK给我们的的工具JConsole
  • Jstack是JDK自带的命令行工具,主要用于线程Dump分析。
  • 具体参考:死锁检测

发生死锁的原因主要由于:

  • 线程之间交错执行
    • 解决:以固定的顺序加锁
  • 执行某方法时就需要持有锁,且不释放
    • 解决:缩减同步代码块范围,最好仅操作共享变量时才加锁
  • 永久等待
    • 解决:使用tryLock()定时锁,超过时限则返回错误信息

 

 

JAVA多线程之 经典“死锁”问题 原创 多线程之死锁详解 ... 阅读详情

相关推荐

基于STM32的多模态智能风扇控制系统设计与实现

本文详细介绍了基于STM32单片机的多模态智能风扇控制系统的设计与实现。系统集成了红外遥控、蓝牙手机控制及人体感应等多模态交互方式,通过PWM技术实现无级调速,并设计了安全优先的控制逻辑。文章从硬件选型、核心原理、软件编程到系统调试,提供了完整的实战指南,适合嵌入式开发爱好者学习与实践。

weixin_28285943的博客 238

哲学家进餐问题

哲学家进餐问题引言互斥锁加锁不得打断奇偶分割线程利用信号量实现伪锁 引言 有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。哲学家有2个状态,思考或者拿起筷子吃饭。如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。 哲学家就餐问题是经典的多线程并发争抢资源的问题,5个人抢5根筷子(外

m0_63515013的博客 634

别再死磕文档了!用国产MBSES软件5分钟上手MBSE建模(保姆级图文教程)

本文通过国产MBSES软件,详细演示了如何在5分钟内完成智能家居系统的MBSE建模。从模块图定义到状态机图构建,再到参数约束验证,全程图文指导,帮助工程师快速掌握基于模型的系统工程方法,显著提升复杂系统设计效率。

weixin_26833503的博客 237

java 线程 防止_Java中的线程死锁是什么?如何避免?

认识线程死锁多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。下面通过一个例子来说明线程死锁,代码模拟了上图的死锁的情况 (代码来源于《并发编程之美》):public class DeadLockDemo {...

weixin_35569158的博客 482

SAP采购含税价转换的底层逻辑解析:ABAP例程如何实现价税分离计算

本文深入解析SAP系统中采购含税价与不含税价的转换机制,重点介绍VOFM例程和ABAP代码实现价税分离计算的方法。通过详细讲解数学原理、税率体系及SAP定价引擎架构,为开发人员提供完整的解决方案,帮助提升采购业务中的价格处理效率和准确性。

weixin_29237635的博客 449

彻底解决Win11 Android模拟器驱动权限问题:手动修改silent_install.bat的保姆级教程

本文提供了一份详细的Win11 Android模拟器驱动权限问题解决方案,重点介绍了手动修改silent_install.bat脚本的两种方法。通过分析问题根源并给出具体代码修改方案,帮助开发者彻底解决Android Studio在Windows 11上安装时遇到的UAC循环弹窗问题,确保android-emulator-hypervisor-driver顺利安装。

dengliugong3918的博客 460

Java 线程死锁及如何避免死锁介绍

死锁是指两个或两个以上的线程在执行过程中,**因争夺资源而造成的互相等待**的现象,在无外力作用的情况下,这些线程会一直相互等待而无法继续运行下去,

weixin_46448719的博客 4820

BambuStudio学习笔记:GCode 类

关键成员解析 核心配置组件 状态跟踪系统 功能模块集成 核心方法剖析 主输出管道 实现多阶段处理: 分层处理流程: 实现智能路径规划: 关键特性: 实现模板故障检测: 采用三级流水线: 支持扩展类型: 实现多通道输出: 采用: 实现: 支持: 支持模块化编译: 典型流程: 实现功能:

zzzkk2009的专栏 925

什么是线程死锁以及如何避免死锁

认识线程死锁 多个线程同时被阻塞,他们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止,最终导致死锁产生。 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会因互相等待而进入死锁状态。 线程死锁示意图 下面通过一个例子来说明线程死锁,代码模拟了上图的死...

happyJared 3826

第四章节 Qt字符串QString详解

QString 的使用方式和 C++标准库的 std::string 字符串的非常相似。

m0_65635427的博客 889

Linux Kernel入门到精通系列讲解(RV-Kernel 篇) 5.6 在kernel 中实现系统复位和系统关机驱动

上一章节`Qemu`篇我们已经实现了我们`SOC`的`power reset`和 `power down` 寄存器,本章节我们就在`Linux driver`中去实现它

DSMGUOGUO的博客 540

线程死锁是什么

线程死锁:两个或两个以上的线程在执行过程中同时被阻塞,它们中的某个或者全部都在等待某个资源被释放,由于线程被无限期的阻塞,系统处于死锁状态或系统产生了死锁,这些永远在互相等待的线程被称为线程死锁 如上图所示,线程A持有资源2,线程B持有资源1,它们都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态 如果想要了解什么是线程阻塞的朋友,可以看我之前发的一篇线程的阻塞线程死锁示例代码如下: 线程 A 通过 synchronized (resource1) 获得 resource1 的监视器锁,然后通

Ai1114的博客 4万+

Qwen-Image(阿里通义千问)技术浅析(一)

Qwen-Image(阿里通义千问多模态模型)是阿里巴巴推出的视觉-语言多模态大模型,能够理解图像内容并完成复杂的跨模态任务。

m0_75253143的博客 673

《菜鸟读并发》什么是线程死锁,怎么解决线程死锁

面试题 什么是线程死锁,? 产生死锁的四个必要条件? 解决线程死锁的办法是什么? 如何避免死锁? 什么是线程死锁? 首先是一个线程需要多把锁,并发的时候多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状...

qq_25843323的博客 3万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

线程死锁详细介绍

死锁是指两个或多个线程互相等待对方占用的资源,而永远无法继续执行下去的情形。更正式的说,死锁是在多线程环境中,多个线程因争夺系统资源而造成的一种互相等待的现象。若无外力干预,这些线程将永远处于等待状态,导致整个程序无法继续运行。

Flying_Fish_roe的博客 2058

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

死锁-java线程死锁

死锁是计算机系统中一个常见的问题,它指的是两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

qq_34358193的博客 1576

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

原创|《菜鸟读并发》什么是线程死锁,怎么解决线程死锁

点击上方“码农进阶之路”,选择“设为星标”回复“面经”获取面试资料面试题什么是线程死锁,?产生死锁的四个必要条件?解决线程死锁的办法是什么?如何避免死锁?什么是线程死锁?首先是一个线程需...

二师兄撒欢之地 1万+

线程死锁——死锁产生的条件

线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于相互等待状态,若无外力作用,它们将无法继续执行下去。造成死锁的原因可以概括成三句话: 上面的程序就是一个典型死锁的例子,为了保证死锁发生的几率,我这里在获得锁之后睡眠了1s。线程1在获得A对象锁之后等了1s去尝试获取B对象锁,这时的;线程2在获得B对象锁之后等待1s去尝试获得A对象锁,这时的;就在它们彼此想获得对方的锁的时候,发生了,并且一直持续下去。 上面提到只有这四个条件都发生时才会出现死锁,那么意思就是说,只要我们破坏其中一个,

qq_43842093的博客 1543

线程池死锁

使用线程池的风险 死锁:虽然死锁可能发生在任何多线程程序中,但线程池引入了另一种死锁情况,其中所有正在执行的线程都在等待等待队列阻塞线程的结果,因为执行的线程不可用。 简言之:业务线程在占用了线程池内所有的资源后又向线程池提交了新的任务,并且要等这些任务完成后才释放资源,而这些新提交的任务根本就没机会被完成 线程泄漏:如果从池中删除线程以执行任务但在任务完成时未返回线程,则会发生线程泄漏。例...

weixin_30252155的博客 1808

线程死锁以及死锁解决的方法

线程死锁以及死锁解决的方法 目录 线程死锁以及死锁解决的方法 一、什么是死锁 二、死锁产生的条件 三、代码演示 1. 死锁产生 2.调整加锁顺序避免死锁产生 3. 加锁时限避免死锁产生 一、什么是死锁 死锁是在两个以及两个以上线程在执行的过程中,由于资源竞争而出现的一种阻塞现象,如果没有外力作用,将会持续下去。 二、死锁产生的条件 互斥条件:每个锁资源一次只能有...

搬砖刘疯狂 1389

线程中死锁的排查

在多线程编程过程中总是会遇到死锁的情况,但是死锁一旦出现,并不报错,也没提示,这种情况下,我们就得学会在线程出现死锁的时候进行排查。 什么叫做死锁: 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。百度百科:死锁。 我个人认识,死锁就...

moxiaolin的博客 3009

如何避免线程死锁

线程死锁是一种特殊的竞争条件,指的是两个或多个线程因相互等待对方持有的资源而无法继续执行的情况。互斥条件:每个资源只能由一个线程占用。占有并等待条件:一个线程已经持有了至少一个资源,并且正在等待获取另一个被其他线程占用的资源。不可剥夺条件:线程已经持有的资源在未完成使用前,不能被其他线程强行剥夺。循环等待条件:存在一个线程循环等待的链,链中的每个线程都在等待另一个线程持有的资源。这四个条件同时满足时,就会发生死锁。避免嵌套锁:尽量减少使用嵌套锁,避免一个线程持有多个锁。使用固定的锁顺序。

Flying_Fish_roe的博客 1091
上一篇: MySQL 插入或者查询中文字符乱码解决
下一篇: git 常用命令
挖坑专业
博客等级 码龄10年 5粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值