死锁(Deadlock)C#
在多线程编程中,死锁(Deadlock)是一种非常常见的问题,通常发生在两个或多个线程相互等待对方持有的锁,导致它们都无法继续执行。要避免死锁,需要了解死锁的四个必要条件以及相应的解决策略。
死锁的形成
死锁是指两个或多个线程相互等待对方释放资源,导致所有线程都无法继续执行。典型的死锁场景如下:
1.线程1拥有资源A,并在等待资源B;
2.线程2拥有资源B,并在等待资源A;
3.两者互相等待对方释放资源,形成了一个循环依赖,导致所有线程都被永久阻塞。
死锁的四个必要条件:
1.互斥条件(Mutex Exclusion):资源一次只能被一个线程占用。
2.持有并等待条件(Hold and Wait):线程持有一个资源并等待获取其他资源。
3.不可剥夺条件(No Preemption):线程已获得的资源条件不能被强行剥夺,只能由线程自己释放。
4.循环等待条件(Circular Wait):存在一组线程,每个线程都在等待下一线程持有的资源,形成一个环形等待。
如果满足以上四个条件,死锁就有可能发生。因此,解决死锁的关键是打破这些条件之一。
避免死锁的策略
1.锁的顺序(Ordering Locks)
确保所有线程按相同的顺序请求锁。这可以打破死锁的循环等待条件。只要所有的线程都以相同的顺序请求资源,死锁就不会发生。
例如,假设有两个锁lock1和lock2,我们确保所有线程总是先获取lock1,然后后获取lock2,避免死锁。
示例:按顺序获取以避免死锁
private static readonly object _lock1 = new object();
private static readonly object _lock2 = new object();public void Thread1Work()
{lock(_lock1)//线程1先获取锁1{Console.WriteLine("Thread 1 acquired lock1");Thread.Sleep(100);lock(_lock2)//线程1然后获取锁2{Console.WriteLine("Thread 1 acquired lock2");}}
}public void Thread2Work()
{lock (_lock1) // 线程2必须按相同顺序获取锁1{Console.WriteLine("Thread 2 acquired lock1");Thread.Sleep(100);lock (_lock2) // 线程2然后获取锁2{Console.WriteLine("Thread 2 acquired lock2");}}
}
如何避免死锁:
• 锁的顺序:通过让线程按照相同的顺序获取锁,可以避免互相等待对方释放锁的问题。
• 结果:Thread1和Thread2都会先获取lock1,然后获取lock2,不会形成死锁。
2.锁的超时机制(Timeout)
使用超时机制来获取锁,如果某个线程在等待锁时超时,则可以放弃操作并避免死锁。这样可以打破持有并等待条件。
示例:使用超时检测潜在的死锁
private static readonly object _lock1 = new object(); // 锁对象1
private static readonly object _lock2 = new object(); // 锁对象2public void Thread1Work()
{if (Monitor.TryEnter(_lock1, TimeSpan.FromSeconds(1))) // 尝试获取锁1,超时时间1秒{try{Console.WriteLine("Thread 1 acquired lock1");// 模拟线程1需要额外的时间处理一些事情Thread.Sleep(100);if (Monitor.TryEnter(_lock2, TimeSpan.FromSeconds(1))) // 尝试获取锁2,超时时间1秒{try{Console.WriteLine("Thread 1 acquired lock2");}finally{Monitor.Exit(_lock2); // 释放锁2}}else{Console.WriteLine("Thread 1 failed to acquire lock2, potential deadlock detected.");}}finally{Monitor.Exit(_lock1); // 释放锁1}}else{Console.WriteLine("Thread 1 failed to acquire lock1, potential deadlock detected.");}
}public void Thread2Work()
{if (Monitor.TryEnter(_lock2, TimeSpan.FromSeconds(1))) // 尝试获取锁2,超时时间1秒{try{Console.WriteLine("Thread 2 acquired lock2");// 模拟线程2需要额外的时间处理一些事情Thread.Sleep(100);if (Monitor.TryEnter(_lock1, TimeSpan.FromSeconds(1))) // 尝试获取锁1,超时时间1秒{try{Console.WriteLine("Thread 2 acquired lock1");}finally{Monitor.Exit(_lock1); // 释放锁1}}else{Console.WriteLine("Thread 2 failed to acquire lock1, potential deadlock detected.");}}finally{Monitor.Exit(_lock2); // 释放锁2}}else{Console.WriteLine("Thread 2 failed to acquire lock2, potential deadlock detected.");}
}
如何避免死锁:
• 锁的超时机制:使用Monitor.TryEnter 来设置获取锁的超时时间。如果超过指定时间无法获取锁,线程可以退出或执行其他操作。
• 结果:如果一个线程未能在指定时间内获取锁,它将放弃尝试并避免陷入死锁。
3.减少锁的持有时间(Minimize Lock Scope)
尽量缩短线程持有锁的时间,减少锁的竞争,进而降低死锁的可能性。只在需要访问共享资源的最小范围内加锁,防止不必要的锁定。
示例:缩短锁的持有时间
private static readonly object _lock1 = new object(); // 锁对象1
private static int _sharedResource = 0; // 共享资源public void IncrementResource()
{// 仅在需要访问共享资源时获取锁lock (_lock1){_sharedResource++; // 修改共享资源Console.WriteLine($"Resource incremented to {_sharedResource} by Thread {Thread.CurrentThread.ManagedThreadId}");}// 锁在这里就释放了,不会在其他不必要的代码块中持有DoOtherWork(); // 其他操作不需要锁定
}private void DoOtherWork()
{// 执行其他不需要锁定的任务Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is doing other work.");
}
如何避免死锁:
• 减少锁的持有时间:尽量缩小锁定的范围,确保只有在修改共享资源时才持有锁。这样可以减少锁竞争,降低死锁发生的机率。
• 结果:线程在修改完共享资源后立刻释放锁,从而使其他线程有机会获得锁。
总结:
死锁形成的条件:
1.互斥条件:每次只有一个线程能够访问资源。
2.持有并等待条件:线程已经持有一个资源,并在等待其他资源。
3.不可剥夺条件:线程持有的资源不能被强行剥夺,必须由线程自己释放。
4.循环等待条件:一组线程形成循环,每个线程都在等待下一个线程释放资源。
避免死锁的策略:
1.锁的顺序:确保所有线程按照相同的顺序获取锁,避免循环等待。
2.锁的超时机制:使用Monitor.TryEnter等等待超时的锁机制,避免无期限等待锁。
3.减少锁的持有时间:尽量缩小锁定范围,减少锁竞争,降低死锁的可能性。
相关文章:
死锁(Deadlock)C#
在多线程编程中,死锁(Deadlock)是一种非常常见的问题,通常发生在两个或多个线程相互等待对方持有的锁,导致它们都无法继续执行。要避免死锁,需要了解死锁的四个必要条件以及相应的解决策略。 死锁的形成 …...
前端-基础CSS 知识总结
1.书写位置:title 标签下方添加 style 双标签,style 标签里面书写 CSS 代码。 <title>CSS 初体验</title> <style>/* 选择器 { } */p {/* CSS 属性 */color: red;} </style><p>体验 CSS</p> <link rel="stylesheet" href=…...
最新版本jdbcutils集成log4j做详细sql日志、自动释放连接...等
maven坐标 <!-- MySQL 8 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version></dependency><!-- Druid连接池 --><dependency><groupId&…...
jQuery快速填充非form数据
jQuery快速填充非form数据 先看看jQuery根据name填充form表单数据 <!DOCTYPE html> <html><head><script src"https://code.jquery.com/jquery-3.6.0.min.js"></script> </head><body><form id"myForm">…...
语音语言模型最新综述! 关于GPT-4o背后技术的尝试
近期,大型语言模型(LLMs)在生成文本和执行各种自然语言处理任务方面展现出了卓越的能力,成为了强大的AI驱动语言理解和生成的基础模型。然而,仅依赖于基于文本模态的模型存在显著局限性。这促使了基于语音的生成模型的发展,使其能够更自然、直观地与人类互动。 为了…...
根据用户选择的行和列数据构造数据结构(跨行跨列)
方案一 这段代码的功能是根据用户选择的行和列数据,生成一个适合复制粘贴的字符串表格。代码会先按列的 id 从小到大排序,再根据行列的选择关系将数据按顺序填入表格,每行之间使用换行符分隔,每列之间使用制表符分隔。如果某一行…...
Spark教程5-基本结构化操作
加载csv文件 df spark.read.format("json").load("/data/flight-data/json/2015-summary.json")Schema 输出Schema df.printSchema()使用Schema读取csv文件,以指定数据类型 from pyspark.sql.types import StructField, StructType, Strin…...
内置数据类型、变量名、字符串、数字及其运算、数字的处理、类型转换
内置数据类型 python中的内置数据类型包括:整数、浮点数、布尔类型(以大写字母开头)、字符串 变量名 命名变量要见名知意,确保变量名称具有描述性和意义,这样可以使得代码更容易维护,使用_可以使得变量名…...
Win/Mac/Android/iOS怎麼刪除代理設置?
設置代理設置的主要構成 IP 地址和端口 這些是代理伺服器配置的最基本組件。代理伺服器的IP地址引導互聯網流量,而端口號指定伺服器上的通信通道。 為什麼要刪除代理設置? 刪除代理設置通常是為了解決網路問題、提高速度、恢復安全性或過渡到新的網路…...
数据结构------手撕顺序表
文章目录 线性表顺序表的使用及其内部方法ArrayList 的扩容机制顺序表的几种遍历方式顺序表的优缺点顺序表的模拟实现洗牌算法 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,…...
UDP(用户数据报协议)端口监控
随着网络的扩展,确保高效的设备通信对于优化网络功能变得越来越重要。在这个过程中,端口发挥着重要作用,它是实现外部设备集成的物理连接器。通过实现数据的无缝传输和交互,端口为网络基础设施的顺畅运行提供了保障。端口使数据通…...
【Java小白图文教程】-05-数组和排序算法详解
精品专题: 01.《C语言从不挂科到高绩点》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482 02. 《SpringBoot详细教程》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12789841.html?spm1001.20…...
OpenCV视觉分析之目标跟踪(1)计算密集光流的类DISOpticalFlow的介绍
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 这个类实现了 Dense Inverse Search (DIS) 光流算法。更多关于该算法的细节可以在文献 146中找到。该实现包含了三个预设参数集,以提…...
Lucas带你手撕机器学习——套索回归
好的,下面我将详细介绍套索回归的背景、理论基础、实现细节以及在实践中的应用,同时还会讨论其优缺点和一些常见问题。 套索回归(Lasso Regression) 1. 背景与动机 在机器学习和统计学中,模型的复杂性通常会影响其在…...
面试中的一个基本问题:如何在数据库中存储密码?
面试中的一个基本问题:如何在数据库中存储密码? 在安全面试中,“如何在数据库中存储密码?”是一个基础问题,但反映了应聘者对安全最佳实践的理解。以下是安全存储密码的最佳实践概述。 了解风险 存储密码必须安全&am…...
XML HTTP Request
XML HTTP Request 简介 XMLHttpRequest(XHR)是一个JavaScript对象,它最初由微软设计,并在IE5中引入,用于在后台与服务器交换数据。它允许网页在不重新加载整个页面的情况下更新部分内容,这使得网页能够实现动态更新,大大提高了用户体验。虽然名字中包含“XML”,但XML…...
TLS协议基本原理与Wireshark分析
01背 景 随着车联网的迅猛发展,汽车已经不再是传统的机械交通工具,而是智能化、互联化的移动终端。然而,随之而来的是对车辆通信安全的日益严峻的威胁。在车联网生态系统中,车辆通过无线网络与其他车辆、基础设施以及云端服务进行…...
当遇到 502 错误(Bad Gateway)怎么办
很多安装雷池社区版的时候,配置完成,访问的时候可能会遇到当前问题,如何解决呢? 客户端,浏览器排查 1.刷新页面和清除缓存 首先尝试刷新页面,因为有时候 502 错误可能是由于网络临时波动导致服务器无法连…...
学习记录:js算法(七十五): 加油站
文章目录 加油站思路一思路二思路三思路四思路五 加油站 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发…...
强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断
强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断 目录 强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断效果一览基本介绍程序设计参考资料 效果一览 基本介绍 EEMD-MPE-KPCA-LSTM(集合经验模态分解-多尺…...
yarn的安装与使用以及与npm的区别(安装过程中可能会遇到的问题)
一、yarn的安装 使用npm就可以进行安装 但是需要注意的一点是yarn的使用和node版本是有关系的必须是16.0以上的版本。 输入以下代码就可以实现yarn的安装 npm install -g yarn 再通过版本号的检查来确定,yarn是否安装成功 yarn -v二、遇到的问题 1、问题描述…...
大数据行业预测
大数据行业预测 编译 李升伟 和所有预测一样,我们必须谨慎对待这些预测,因为其中一些预测可能成不了事实。当然,真正改变游戏规则的创新往往出乎意料,甚至让最警惕的预言家也措手不及。所以,如果在来年发生了一些惊天…...
可能是NextJs(使用ssr、api route)打包成桌面端(nextron、electron、tauri)的最佳解决方式
可能是NextJs(使用ssr、api route)打包成桌面端(nextron、electron、tauri)的最佳解决方式 前言 在我使用nextron(nextelectron)写了一个项目后打包发现nextron等一系列桌面端框架在生产环境是不支持next的ssr也就是api route功能的这就导致我非常难受&…...
二百七十、Kettle——ClickHouse中增量导入清洗数据错误表
一、目的 比如原始数据100条,清洗后,90条正确数据在DWD层清洗表,10条错误数据在DWD层清洗数据错误表,所以清洗数据错误表任务一定要放在清洗表任务之后。 更关键的是,Hive中原本的SQL语句,放在ClickHouse…...
CentOS6升级OpenSSH9.2和OpenSSL3
文章目录 1.说明2.下载地址3.升级OpenSSL4.安装telnet 服务4.1.安装 telnet 服务4.2 关闭防火墙4.2.使用 telnet 连接 5.升级OpenSSH5.1.安装相关命令依赖5.2.备份原 ssh 配置5.3.卸载原有的 OpenSSH5.4.安装 OpenSSH5.5.修改 ssh 配置文件5.6关闭 selinux5.7.重启 OpenSSH 1.说…...
2024 年 MathorCup 数学应用挑战赛——大数据竞赛-赛道 A:台风的分类与预测
2024年MathorCup大数据挑战赛-赛道A初赛--思路https://download.csdn.net/download/qq_52590045/89922904↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓…...
kotlin实现viewpager
说明:kotlin tablayout viewpager adapter实现滑动界面 效果图 step1: package com.example.flushfragmentdemoimport androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.…...
RabbitMQ最新版本4.0.2在Windows下的安装及使用
RabbitMQ 是一个开源的消息代理和队列服务器,提供可靠的消息传递和队列服务。它支持多种消息协议,包括 AMQP、STOMP、MQTT 等。本文将详细介绍如何在 Windows 系统上安装和使用最新版本的 RabbitMQ 4.0.2。 前言 RabbitMQ 是用 Erlang 语言开发的 AMQP&…...
东方博宜1180 - 数字出现次数
问题描述 有 50 个数( 0∼19),求这 50个数中相同数字出现的最多次数为几次? 输入 50 个数字。 输出 1 个数字(即相同数字出现的最多次数)。 样例 输入 1 10 2 0 15 8 12 7 0 3 15 0 15 18 16 7 17 16 9 …...
LeetCode: 3274. 检查棋盘方格颜色是否相同
一、题目 给你两个字符串 coordinate1 和 coordinate2,代表 8 x 8 国际象棋棋盘上的两个方格的坐标。 以下是棋盘的参考图。 如果这两个方格颜色相同,返回 true,否则返回 false。 坐标总是表示有效的棋盘方格。坐标的格式总是先…...
外贸网站建设如何做/今天刚刚发生的新闻事故
JDK有个ServiceLoader类,在java.util包里,支持按约定目录/META-INF/services去找到接口全路径命名的文件,读取文件内容得到接口实现类的全路径,加载并实例化。如果我们在自己的代码中定义一个接口,别人按接口实现并打包…...
wordpress加密视频播放器/站长工具ping检测
这两个工具类都是基于之前介绍的注解来完成的第一个工具类是ExcelImportUtil Excel导入工具类两个方法1.从本地导入2.流导入参数基本上一直,导入文件,导如对应的实体,导入参数第二中方法相对来说我们用的比较多,我们从前天传输的获取流,然后返回一个list对象第二个类 导出类Exc…...
用自己的电脑做服务器建网站/关键词推广哪家好
ARM系列之RM 平台安全架构PSA 浅析 1、背景2、PSA安全认证2.1 什么是PSA?2.2 功能性 API 认证2.3 PSA安全认证(待完善)3、专用的开源安全固件代码1、背景 在互联网飞速发展过程中,安全问题始终贯穿其中。在这场安全保卫战中&…...
独立网站做外贸怎么样/让百度收录自己的网站
堆(Heap)栈(Stack) 1、内存分配方面: 堆:一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式是类似于链表。可能…...
网站流量100g/自己搭建网站需要什么
完整微信小程序(Java后端) 技术贴目录清单页面(必看) 图标。组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。 属性类型默认值必填说明最低版本typestring是icon的类型,有效值:success, success_no_circle…...
工程公司起名大全/广东优化疫情防控措施
目录 3.1过程语句 3.2任务、函数和void函数 3.3任务和函数概述 3.3.1在子程序中去掉begin...end 3.4子程序参数 3.4.1C语言风格的子程序参数 3.4.2参数的方向 3.4.3高级的参数类型 3.4.4参数的缺省值 3.4.5采用名字进行参数传递 3.4.6常见的代码错误 3.5子程序的返…...