当前位置: 首页 > news >正文

【多线程 - 11、死锁】

死锁

1、介绍

在 Java 中使用多线程,就会有可能导致死锁问题。死锁会让程序一直卡住,程序不再往下执行。只能通过中止并重启的方式来让程序重新执行。要尽可能避免死锁的情况发生

2、造成死锁的原因

互斥条件:
同一资源同时只能由一个线程读取

不可抢占条件:
不能强行剥夺线程占有的资源

请求和保持条件:
请求其他资源的同时对自己手中的资源保持不放

循环等待条件:
在相互等待资源的过程中,形成一个闭环

预防死锁:
只需要破坏其中一个条件即可,比如使用定时锁、尽量让线程用相同的加锁顺序,加锁超时或自动释放,死锁检测算法等等

3、避免死锁的方法

  • 固定加锁的顺序(针对锁顺序死锁)
  • 开放调用(针对对象之间协作造成的死锁)
  • 使用定时锁–>tryLock();如果等待获取锁时间超时,则抛出异常而不是一直等待

二、顺序死锁

例子

public class ThreadTest6 {public static void main(String[] args) {Demo demo = new Demo();new Thread(demo,"1").start();new Thread(demo,"2").start();new Thread(demo,"3").start();new Thread(demo,"4").start();}}class Demo implements Runnable{Account a = new Account("A",1000);Account b = new Account("B",1000);@Overridepublic void run() {transferMoney(a,b,100);transferMoney(b,a,100);}public void  transferMoney(Account fromAccount, Account toAccount,double money) {synchronized (fromAccount) {System.out.println("线程" + Thread.currentThread().getName() + "得到锁" + fromAccount.getName());synchronized (toAccount) {System.out.println("线程" + Thread.currentThread().getName() + "得到锁" + toAccount.getName());if(fromAccount.getMoney() < money) {System.out.println("余额不足");} else {fromAccount.setMoney(fromAccount.getMoney()-money);toAccount.setMoney(toAccount.getMoney() + money);System.out.println("转账后:" + fromAccount.getName() + "有:" + fromAccount.getMoney());System.out.println("转账后:" + toAccount.getName() + "有:" + toAccount.getMoney());}}}}
}
class Account{public Account(String name, double money) {this.name = name;this.money = money;}private String name;private double money;public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}}

代码有可能会发生死锁:如果两个线程同时调用 transferMoney(),线程A 从 X账户 向 Y账户 转账,线程B 从 账户Y 向 账户X 转账,那么就会发生死锁

避免死锁

上面 transferMoney() 发生死锁的原因是因为加锁顺序不一致而出现的;如果所有线程以固定的顺序来获得锁,那么程序中就不会出现锁顺序死锁问题

上面的例子改造:

public class InduceLockOrder {// 额外的锁、避免两个对象hash值相等的情况(即使很少)private static final Object tieLock = new Object();public void transferMoney(final Account fromAcct,  final Account toAcct, final DollarAmount amount)  throws InsufficientFundsException {class Helper {public void transfer()  throws InsufficientFundsException {if (fromAcct.getBalance().compareTo(amount) < 0)throw new InsufficientFundsException();else {fromAcct.debit(amount);toAcct.credit(amount);}}}// 得到锁的hash值int fromHash = System.identityHashCode(fromAcct);int toHash = System.identityHashCode(toAcct);// 根据hash值来上锁if (fromHash < toHash) {synchronized (fromAcct) {synchronized (toAcct) {new Helper().transfer();}}} else if (fromHash > toHash) {// 根据hash值来上锁synchronized (toAcct) {synchronized (fromAcct) {new Helper().transfer();}}} else {// 额外的锁、避免两个对象hash值相等的情况(即使很少)synchronized (tieLock) {synchronized (fromAcct) {synchronized (toAcct) {new Helper().transfer();}}}}}
}

得到对应的 hash值 来固定加锁的顺序,这样就不会发生死锁的问题

三、协作对象之间发生死锁

发生条件

A对象 的一个同步方法调用了 B对象 的同步方法。且有,B对象 的一个同步方法调用了 A对象 的一个同步方法。则可能发生:A线程 得到了 A对象 锁,B对象 同时得到了 B对象 锁,都不会释放,且都无法继续执行,就发生了死锁

开放调用避免死锁

在协作对象之间发生死锁中,主要是因为在调用某个方法时就需要持有锁,并且在方法内部也调用了其他带锁的方法;如果在调用某个方法时不需要持有锁,那么这种调用被称为开放调用;可以在方法中使用同步代码块来实现同步,调用另一对象的同步方法不放在同步代码块中,就解决了问题

四、定时锁避免死锁

tryLock 方法

使用显式 Lock 锁,在获取锁时使用 tryLock() 方法。当等待超过时限的时候,tryLock() 不会一直等待,而是返回错误信息

tryLock 是防止自锁的一个重要方式

tryLock() 方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待

例子

public class tryLock {public static void main(String[] args) {System.out.println("开始");final Lock lock = new ReentrantLock();new Thread() {@Overridepublic void run() {String tName = Thread.currentThread().getName();if (lock.tryLock()) {System.out.println(tName + "获取到锁!");} else {System.out.println(tName + "获取不到锁!");return;}try {for (int i = 0; i < 5; i++) {System.out.println(tName + ":" + i);}Thread.sleep(5000);} catch (Exception e) {System.out.println(tName + "出错了!!!");} finally {System.out.println(tName + "释放锁!!");lock.unlock();}}}.start();new Thread() {@Overridepublic void run() {String tName = Thread.currentThread().getName();if (lock.tryLock()) {System.out.println(tName + "获取到锁!");} else {System.out.println(tName + "获取不到锁!");return;}try {for (int i = 0; i < 5; i++) {System.out.println(tName + ":" + i);}} catch (Exception e) {System.out.println(tName + "出错了!!!");} finally {System.out.println(tName + "释放锁!!");lock.unlock();}}}.start();System.out.println("结束");}
}

五、总结

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

线程之间交错执行
解决: 以固定的顺序加锁

执行某方法时就需要持有锁,且不释放
解决: 缩减同步代码块范围,最好仅操作共享变量时才加锁

永久等待
**解决:**n使用 tryLock() 定时锁,超过时限则返回错误信息

相关文章:

【多线程 - 11、死锁】

死锁 1、介绍 在 Java 中使用多线程&#xff0c;就会有可能导致死锁问题。死锁会让程序一直卡住&#xff0c;程序不再往下执行。只能通过中止并重启的方式来让程序重新执行。要尽可能避免死锁的情况发生 2、造成死锁的原因 互斥条件&#xff1a; 同一资源同时只能由一个线程读…...

flask实现session开发

要在Flask应用中实现会话&#xff08;session&#xff09;开发&#xff0c;你可以使用Flask内置的session模块。以下是一个示例代码&#xff0c;演示在Flask应用中启用和使用会话功能&#xff1a; from flask import Flask, session, redirect, url_for, requestapp Flask(__…...

paddle dataset

paddle实现图像旋转 import numpy as np from PIL import Image from matplotlib import pyplot as plt from paddle.vision.transforms import functional as F import cv2imagecv2.imread(./1.jpg) imagecv2.cvtColor(image,cv2.COLOR_BGR2RGB)# 图像旋转 opencv # imgR90 …...

接口自动化测试实战:JMeter+Ant+Jenkins+钉钉机器人群通知完美结合

前言 一、本地JAVA环境安装配置,安装JAVA8和JAVA17 二、安装和配置Jmeter 三、安装和配置ant 四、jmeter + ant配置 五、jenkins安装和配置持续构建项目 六、jenkins配置流程 前言 搭建jmeter+ant+jenkins环境有些前提条件,那就是要先配置好java环境,本地java环境…...

HAL库STM32串口开启DMA接收数据

STM32CubeMx的配置 此博客仅仅作为记录&#xff0c;这个像是有bug一样&#xff0c;有时候好使&#xff0c;有时候不好&#xff0c;所以趁现在好使赶紧记录一下&#xff0c;很多地方用到串口接收数据&#xff0c;DMA又是一种非常好的接收方式&#xff0c;可以节约CPU的时间&…...

Web安全研究(五)

Automated WebAssembly Function Purpose Identification With Semantics-Aware Analysis WWW23 文章结构 introbackgroundsystem design abstraction genapplying abstractionsclassifier data collection and handling data acquisitionstatistics of collected datamodule-…...

2023.11.17-hive调优的常见方式

目录 0.设置hive参数 1.数据压缩 2.hive数据存储格式 3.fetch抓取策略 4.本地模式 5.join优化操作 6.SQL优化(列裁剪,分区裁剪,map端聚合,count(distinct),笛卡尔积) 6.1 列裁剪: 6.2 分区裁剪: 6.3 map端聚合(group by): 6.4 count(distinct): 6.5 笛卡尔积: 7…...

ts 联合react 实现ajax的封装,refreshtoken的功能

react ts混合双打&#xff0c;实现ajax的封装&#xff0c;以及401的特殊处理 import axios from axios import {AMDIN_EXPIRES_KEY,AMDIN_KEY,AMDIN_REFRESH_EXPIRES_KEY,AMDIN_REFRESH_KEY,COMMID_KEY,getToken,removeToken } from ../utils/user-token import { showMessage…...

CISP模拟试题(一)

免责声明 文章仅做经验分享用途,利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行承担!!! 1.下面关于信息安全保障的说法错误的是:C A.信息安全保障的概念是与信息安全的概念同时产生的 …...

轻量封装WebGPU渲染系统示例<35>- HDR环境数据应用到PBR渲染材质

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/BasePbrMaterialTest.ts 当前示例运行效果: 微调参数之后的效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: export class BasePbrMateri…...

春秋云境靶场CVE-2022-28512漏洞复现(sql手工注入)

文章目录 前言一、CVE-2022-28512靶场简述二、找注入点三、CVE-2022-28512漏洞复现1、判断注入点2、爆显位个数3、爆显位位置4 、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。…...

数字化文化的守护之星:十八数藏的非遗创新之道

在数字时代的浪潮中&#xff0c;十八数藏犹如一颗璀璨的守护之星&#xff0c;为传统文化注入了新的生命力。这个非遗创新项目以数字化为工具&#xff0c;以守护为使命&#xff0c;开辟了文化传承的新航道。 十八数藏是文化数字守护的引领者&#xff0c;通过数字技术&#xff0…...

[机缘参悟-119] :反者道之动与阴阳太极

目录 一、阴阳对立、二元对立的规律 1.1 二元对立 1.2 矛盾的对立与统一 二、阴阳互转、阴阳变化、变化无常 》无序变化和有序趋势的规律 三、阴阳合一、佛魔一体、善恶同源 四、看到积极的一面 五、反者道之动 5.1 概述 5.2 "否极泰来" 5.3 “乐极生悲”…...

Docker搭建Redis集群

Docker搭建Redis集群 创建一个专属redis的网络 docker network create redis --subnet 172.38.0.0/16通过shell脚本创建并启动6个redis服务 #通过脚本一次创建6个redis配置 for port in $(seq 1 6); \ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/n…...

学习Opencv(蝴蝶书/C++)代码——2.OpenCV初探

文章目录 0. 图像读取与显示1. 视频文件读取与操作1.1 示例代码1.1 OpenCV支持的视频格式2. 加入滑动条2.1 示例代码2.2 报错/Warning2.3 关于toolbar3. 简易视频播放器3.1 OpenCV检测方向键被按下3.1.1 Windows下3.1.2 linux下3.1 方向键控制视频变化4. 简单的变换5. 写视频5.…...

基于AVR单片机的便携式心电监测设备设计与实现

基于AVR单片机的便携式心电监测设备是一种常用的医疗设备&#xff0c;用于随时监测和记录人体的心电信号。本文将介绍便携式心电监测设备的设计原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 设计概述 便携式心电监测设备是一种小巧、方便携带的设备&#xff0c;能够…...

微机原理_14

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1,下面寻址方式的操作数不在存储器中的是(&#xff09; A. 堆栈寻址 B. 寄存器间址 C.寄存器寻址 D. 直接寻址 2,条件转移指令JNE的条件是(&#xff09; A. CF…...

【Flink】核心概念:并行度与算子链

并行度&#xff08;Parallelism&#xff09; 当要处理的数据量非常大时&#xff0c;我们可以把一个算子操作&#xff0c;“复制”多份到多个节点&#xff0c;数据来了之后就可以到其中任意一个执行。这样一来&#xff0c;一个算子任务就被拆分成了多个并行的“子任务”&#x…...

milvus采坑一:启动服务就会挂掉

原因一 硬盘满了&#xff0c;Eric数据文件存储在硬盘上&#xff0c;当硬盘不足&#xff0c;它就会启动后就挂掉。 此时pymilvus连接一直是timeout。 解决方法&#xff1a;更换存储路径。...

WPF Visual, UIElement, FrameworkElement, Control这些类的区别

在WPF (Windows Presentation Foundation) 中&#xff0c;Visual, UIElement, FrameworkElement, 和 Control 这些类是一个类层次结构&#xff0c;它们分别在 WPF 的 UI 元素和控件模型中提供了不同级别的功能。下面是这些类的详细介绍&#xff1a; Visual&#xff1a;这是所有…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...