死锁(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();  // 锁对象2

public 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.减少锁的持有时间:尽量缩小锁定范围,减少锁竞争,降低死锁的可能性。

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

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

相关文章

Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程

什么是 Pyramidal Flow? Pyramidal Flow 是由快手科技、北京大学和北京邮电大学联合推出的开源视频生成模型,它是完全开源的,发布在 MIT 许可证下,允许商业使用、修改和再分发。该模型能够通过文本描述生成最高10秒、分辨率为128…

铜业机器人剥片 - SNK施努卡

SNK施努卡有色行业电解车间铜业机器人剥片 铜业机器人剥片技术是针对传统人工剥片效率低下、工作环境恶劣及生产质量不稳定的痛点而发展起来的自动化解决方案。 面临人工剥片的诸多挑战,包括低效率、工作环境差、人员流动大以及产品质量控制不精确等问题。 人工剥片…

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目

Idea基于JRbel实现项目热部署修改Java、Xml文件无需重启项目 1.JRbel服务安装2.JRbel插件安装3.JRbel配置 1.JRbel服务安装 直接装插件的话,需要用到一个服务地址,服务下载链接:(现在没时间搞,会尽快加上)…

合合信息亮相PRCV大会,探讨生成式AI时代的内容安全与系统构建加速

一、前言 在人工智能技术的飞速发展下,生成式AI已经成为推动社会进步的重要力量。然而,随着技术的不断进步,内容安全问题也日益凸显。如何确保在享受AI带来的便利的同时,保障信息的真实性和安全性,已经成为整个行业待解…

Jmeter自动化实战

前言 由于系统业务流程很复杂,在不同的阶段需要不同的数据,且数据无法重复使用,每次造新的数据特别繁琐,故想着能不能使用jmeter一键造数据 创建录制模板 录制模板参考 首先创建一个录制模板 因为会有各种请求头,cookies,签名,认证信息等原因,导致手动复制粘贴的的全面导致接…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中,我们…

NVIDIA发布Nemotron-70B-Instruct,超越GPT-4o和Claude 3.5的AI模型

一、Nemotron-70B-Instruct 是什么 Nemotron-70B-Instruct 是由 NVIDIA 基于 Meta 的 Llama 3.1-70B 模型开发的先进大语言模型(LLM)。该模型采用了新颖的神经架构搜索(Neural Architecture Search,NAS)方法和知识蒸馏…

【华为HCIP实战课程二十】OSPF特殊区域NSSA配置详解,网络工程师

一、NSSA(Not So Stubby Area)区域 在NSSA区域内可以拥有ASBR,并且重分发进入OSPF的路由是以7类LSA形式存在,该类型的LSA只能存在于NSSA区域内不接收5类LSA,ABR过滤外部进入该区域的4 5类LSA,可以引入外部…

题解 力扣 LeetCode 739 每日温度 C++

题目传送门: 739. 每日温度 - 力扣(LeetCode)https://leetcode.cn/problems/daily-temperatures/description/ 思路: 就是单调栈的思路,具体见代码 不知道单调栈的,可以看我的这篇文章: 数…

web3对象如何连接以太网络节点

实例化web3对象 当我们实例化web3对象,我们一般开始用本地址,如下 import Web3 from web3 var web3 new Web3(Web3.givenProvider || ws://localhost:5173)我们要和以太网进行交互,所以我们要将’ws://localhost:5173’的本地地址换成以太…

【Linux学习】(6)编译器gcc/g++

前言 本节重点:掌握gcc/g编译器的使用,并了解其过程,原理 一、Linux编译器-gcc/g使用 1. gcc/g的基本使用 在前面我们学习了vim,知道如何在Linux中编写代码。但又是如何编译代码的?——在Linux中我们编译代码使用的是…

UDP(用户数据报协议)端口监控

随着网络的扩展,确保高效的设备通信对于优化网络功能变得越来越重要。在这个过程中,端口发挥着重要作用,它是实现外部设备集成的物理连接器。通过实现数据的无缝传输和交互,端口为网络基础设施的顺畅运行提供了保障。端口使数据通…

Linux中安装配置SQLite3,并实现C语言与SQLite3的交互。

前言 SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。本次实验介绍在Linux上实现C语言和SQLite3的交互,利用C语言编写相关语句,连接数据库、操作数…

【数据结构初阶】二叉树---堆

二叉树-堆的实现 一、树的概念(什么是树)二、二叉树的概念及结构2.1 二叉树的概念2.2 二叉树的性质2.3 二叉树存储结构 三、二叉树的顺序结构3.1 堆的概念及结构3.2 堆的向下调整算法3.3堆的创建 四、堆的代码实现4.1 堆的初始化4.2 堆的销毁4.3 堆的插入…

如何从iconfont中获取字体图标并应用到微信小程序中去?

下面我们一一个微信小程序的登录界面的制作为例来说明,如何从iconfont中获取字体图标是如何应用到微信小程序中去的。首先我们看效果。 这里所有的图标,都是从iconfont中以字体的形式来加载的,也就是说,我们自始至终没有使用一张…

jenkins 自动化部署Springboot 项目

一、安装docker 1.更新yum命令 yum -y update2.查看机器有残留的docker服务,有就卸载干净 查看docker 服务 rpm -qa |grep docker卸载docker sudo yum remove docker-ce docker-ce-cli containerd.io sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/contai…

linux下的进程等待(wait、waitpid)

目录 引言 进程等待的必要性 见见猪跑:是什么 怎么办 多个子进程时 阻塞等待 非阻塞轮询 参数一: 参数二 进程等待的原理 进程退出相关的宏 第三个参数option(设置等待的方式) 引言 在Linux操作系统中,进程…

Jmeter实际应用

环境准备 JDK1.8Jmeter 5.6.3 下载地址Jmeter 插件 下载地址 放到lib/ext下 常用命令 # 启动 sh jmeter# 集群模式下启动节点,不启动用不了集群 sh jmeter-server#生成ssl需要的证书, 这里会要求输入个密码,是要在jmeter中用的 keytool -import -ali…

Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工…

基于SSM+小程序的垃圾分类管理系统(垃圾2)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM小程序的垃圾分类管理系统实现了管理员及用户。 1、管理员功能结构图,管理员功能有个人中心,管理员管理,基础数据管理、论坛管理、垃圾信息管理…