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

Linux下的线程同步与死锁避免

文章目录

      • 死锁的四个必要条件
      • 破坏死锁条件的方法
        • 破坏互斥条件
          • 使用读写锁(`pthread_rwlock_t`)
        • 破坏持有并等待条件
          • 一次性申请所有资源
        • 破坏不可剥夺条件
          • 使用超时锁定机制
          • 可重入锁(递归锁)
        • 破坏循环等待条件
          • 统一锁顺序

在 Linux 下进行多线程编程时,线程同步是至关重要的部分,尤其是在多个线程需要共享资源的场景中。尽管同步机制能够解决竞争条件,但它也带来了死锁的风险。死锁是指多个线程互相等待对方释放锁而导致永远无法继续执行的现象。为了避免死锁,可以从破坏导致死锁的四个必要条件入手。本文将从这四个条件展开,探讨如何通过破坏这些条件来避免死锁。


死锁的四个必要条件

根据操作系统中的经典理论,死锁的产生必须满足以下四个必要条件:

  1. 互斥条件:某些资源是只能被一个线程独占使用的。
  2. 持有并等待条件:一个线程已经持有了某个资源,同时它在等待获取其他线程持有的资源。
  3. 不可剥夺条件:已经获得的资源不能被强行剥夺,线程只能主动释放资源。
  4. 循环等待条件:存在一个线程循环等待的链,链中的每个线程都在等待下一个线程持有的资源。

为了避免死锁,可以通过破坏至少其中一个条件来打破死锁局面。下面,我们将详细探讨这四个条件以及如何在 Linux 下的线程同步机制中破坏这些条件来避免死锁。


破坏死锁条件的方法

破坏互斥条件

互斥条件是指某些资源只能被一个线程独占使用,无法同时被多个线程访问。在某些情况下,我们可以通过将资源转换为可共享的资源来破坏互斥条件,从而避免死锁。

使用读写锁(pthread_rwlock_t

读写锁允许多个线程同时读取数据,而只有在写操作时需要独占锁。这种机制可以提高并发性,避免因读操作而产生死锁。

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;void* reader(void* arg) {pthread_rwlock_rdlock(&rwlock); // 获取读锁// 执行读操作pthread_rwlock_unlock(&rwlock); // 释放锁return NULL;
}void* writer(void* arg) {pthread_rwlock_wrlock(&rwlock); // 获取写锁// 执行写操作pthread_rwlock_unlock(&rwlock); // 释放锁return NULL;
}

通过使用读写锁,我们可以允许多个线程并发读取数据,从而减少死锁的可能性。


破坏持有并等待条件

持有并等待条件指的是一个线程持有一个资源,同时等待其他资源的情况。为了避免这种情况,我们可以在申请资源之前,确保线程不占有其他资源,或者一次性申请所有所需资源。

一次性申请所有资源

如果线程需要多个资源,可以采用一次性申请所有资源的策略。即,线程只有在能够获取所有资源时才会继续执行,否则会释放已经持有的资源,避免持有并等待的发生。

pthread_mutex_t lock1, lock2;void* task(void* arg) {// 一次性申请所有资源if (pthread_mutex_trylock(&lock1) == 0) {if (pthread_mutex_trylock(&lock2) == 0) {// 执行任务pthread_mutex_unlock(&lock2);}pthread_mutex_unlock(&lock1);}return NULL;
}

通过一次性申请资源,线程要么成功获取所有资源并继续执行,要么立即释放资源,减少持有并等待的风险。


破坏不可剥夺条件

不可剥夺条件是指资源一旦被线程占有,其他线程就无法强制剥夺。我们可以引入超时机制或设计自愿释放机制来打破这一条件。

使用超时锁定机制

我们可以通过使用 pthread_mutex_trylock() 或在某些高级锁机制中使用超时锁定机制,让线程在等待资源时不会无限期等待。如果线程无法在规定的时间内获得资源,它可以选择放弃并执行其他操作。

pthread_mutex_t lock;void* task(void* arg) {if (pthread_mutex_trylock(&lock) == 0) {// 成功获取锁,执行任务pthread_mutex_unlock(&lock);} else {// 获取锁失败,执行其他操作或等待一段时间后重试}return NULL;
}

通过这种方式,线程不会无限期地等待资源,从而避免了死锁的发生。

可重入锁(递归锁)

递归锁(pthread_mutex_t 使用 PTHREAD_MUTEX_RECURSIVE 属性初始化)允许同一线程多次锁定同一个互斥锁,而不发生死锁。当线程完成任务后,它需要相应次数地解锁。

pthread_mutex_t recursive_mutex;pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&recursive_mutex, &attr);

递归锁通过允许同一线程多次锁定相同的资源,避免了某些递归调用中的死锁风险。


破坏循环等待条件

循环等待条件是指存在一个线程循环等待链,每个线程都在等待下一个线程持有的资源。我们可以通过强制规定获取锁的顺序来打破循环等待。

统一锁顺序

为避免循环等待,所有线程都应按照相同的顺序请求资源。例如,如果所有线程都按顺序 lock1 -> lock2 -> lock3 获取锁,便不会产生循环等待。

pthread_mutex_t lock1, lock2;void* task1(void* arg) {pthread_mutex_lock(&lock1); // 按照固定顺序加锁pthread_mutex_lock(&lock2);// 执行任务pthread_mutex_unlock(&lock2);pthread_mutex_unlock(&lock1);
}void* task2(void* arg) {pthread_mutex_lock(&lock1); // 同样的顺序pthread_mutex_lock(&lock2);// 执行任务pthread_mutex_unlock(&lock2);pthread_mutex_unlock(&lock1);
}

通过保持锁的获取顺序一致,线程避免了陷入循环等待,从而有效地防止死锁。

相关文章:

Linux下的线程同步与死锁避免

文章目录 死锁的四个必要条件破坏死锁条件的方法破坏互斥条件使用读写锁(pthread_rwlock_t) 破坏持有并等待条件一次性申请所有资源 破坏不可剥夺条件使用超时锁定机制可重入锁(递归锁) 破坏循环等待条件统一锁顺序 在 Linux 下进…...

【Python爬虫实战】Selenium自动化网页操作入门指南

#1024程序员节|征文# 🌈个人主页:易辰君-CSDN博客 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、准备工作 (一)安装 Selenium 库 &#xff0…...

mono源码交叉编译 linux arm arm64全过程

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...

矩阵的可解性:关于Ax=b的研究

上一篇文章讲解了如何求解 A x 0 Ax0 Ax0,得到 A A A的零空间。 类似的,我们今天学习的是如何求解 A x b Axb Axb,并以此加强你对线性代数中,代数与空间的理解。 同样的,我们举与上一次一样的例子,矩阵 …...

10.22.2024刷华为OD C题型(三)--for循环例子

脚踝动了手术,现在宾馆恢复,伤筋动骨一百天还真不是说笑的,继续努力吧。 文章目录 靠谱的车灰度图恢复灰度图恢复 -- for循环使用例子 靠谱的车 https://www.nowcoder.com/discuss/564514429228834816 这个题目思路不难,就是要自…...

QT:MaintenanceTool 模块安装工具

QT的MaintenanceTool 工具对已安装的 Qt 进行卸载、修复等其他操作时提示At least one valid and enabled repository required for this action to succeed 解决方式:在设置中添加一个临时的仓库 https://mirrors.tuna.tsinghua.edu.cn/qt/online/qtsdkrepositor…...

同标签实现监听LocalStorage

使用 React 生命周期函数 useEffect来监听和处理 LocalStorage 的变化 import React, { useEffect } from react;const LocalStorageListener () > {useEffect(() > {// 注册监听器const handleStorageChange (event) > {if (event.key myKey) {console.log(注册…...

JAVA高性能缓存项目

版本一 代码实现 import java.util.HashMap; import java.util.concurrent.TimeUnit;public class CacheExample01 {private final static HashMap<String, Integer> cache new HashMap<>();public static Integer check(String userId) throws InterruptedExce…...

智慧农业大数据平台:智汇田园,数驭未来

智慧农业大数据平台 计讯物联智慧农业大数据平台是一个集管理数字化、作业自动化、生产智能化、产品绿色化、环境信息化、服务现代化于一体的多功能监管系统。它通过与硬件产品的搭配使用&#xff0c;实现对农业生产全过程的实时监测、精准控制和科学管理。该平台集成了多个数…...

Go语言基础教程:可变参数函数

Go 语言允许函数接收可变数量的参数&#xff0c;这种特性对于处理数量不确定的参数特别有用。在本教程中&#xff0c;我们将通过示例代码讲解如何定义和使用 Go 的可变参数函数。 package mainimport "fmt"// 定义一个可变参数函数 sum&#xff0c;接收任意数量的整…...

高并发场景下解决并发数据不一致

简单的场景: 全量数据更新的情况下, 不在乎同一秒的请求都必须要成功, 只留下最新的更新请求数据 方案常用的是 1、数据库增加时间戳标识实现的乐观锁, 请求参数从源头带上微秒或者毫秒时间戳数据库存储, 然后在更新SQL语句上比较 (数据库的时间 < 参数传递的时间) 例如: A…...

OpenAI GPT-o1实现方案记录与梳理

本篇文章用于记录从各处收集到的o1复现方案的推测以及介绍 目录 Journey Learning - 上海交通大学NYUMBZUAIGAIRCore IdeaKey QuestionsKey TechnologiesTrainingInference A Tutorial on LLM Reasoning: Relevant methods behind ChatGPT o1 - UCL汪军教授Core Idea先导自回归…...

Excel:vba实现生成随机数

Sub 生成随机数字()Dim randomNumber As IntegerDim minValue As IntegerDim maxValue As Integer 设置随机数的范围(假入班级里面有43个学生&#xff0c;学号是从1→43)minValue 1maxValue 43 生成随机数(在1到43之间生成随机数)randomNumber Application.WorksheetFunctio…...

Python | Leetcode Python题解之第506题相对名次

题目&#xff1a; 题解&#xff1a; class Solution:desc ("Gold Medal", "Silver Medal", "Bronze Medal")def findRelativeRanks(self, score: List[int]) -> List[str]:ans [""] * len(score)arr sorted(enumerate(score), …...

安全见闻(6)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;安全见闻&#xff08;6&#xff09;_哔哩哔哩_bilibili 学无止境&#xff0c;开拓自己的眼界才能走的更远 本文主要讲解通讯协议涉及的安全问题。…...

Promise、async、await 、异步生成器的错误处理方案

1、Promise.all 的错误处理 Promise.all 方法接受一个 Promise 数组&#xff0c;并返回所有解析 Promise 的结果数组&#xff1a; const promise1 Promise.resolve("one"); const promise2 Promise.resolve("two");Promise.all([promise1, promise2]).…...

腾讯云:数智教育专场-学习笔记

15点13分2024年10月21日&#xff08;短短5天的时间&#xff0c;自己的成长速度更加惊人&#xff09;-开始进行“降本增效”学习模式&#xff0c;根据小米手环对于自己的行为模式分析&#xff08;不断地寻找数据之间的关联性&#xff09;&#xff0c;每天高效记忆时间&#xff0…...

Ovis: 多模态大语言模型的结构化嵌入对齐

论文题目&#xff1a;Ovis: Structural Embedding Alignment for Multimodal Large Language Model 论文地址&#xff1a;https://arxiv.org/pdf/2405.20797 github地址&#xff1a;https://github.com/AIDC-AI/Ovis/?tabreadme-ov-file 今天&#xff0c;我将分享一项重要的研…...

python的Django的render_to_string函数和render函数模板的使用

一、render_to_string render_to_string 是 Django 框架中的一个便捷函数&#xff0c;用于将模板渲染为字符串。 render_to_string(template_name.html, context, requestNone, usingNone) template_name.html&#xff1a;要渲染的模板文件的名称。context&#xff1a;传递给…...

基于Python大数据的王者荣耀战队数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...