Linux下的线程同步与死锁避免
文章目录
- 死锁的四个必要条件
- 破坏死锁条件的方法
- 破坏互斥条件
- 使用读写锁(`pthread_rwlock_t`)
- 破坏持有并等待条件
- 一次性申请所有资源
- 破坏不可剥夺条件
- 使用超时锁定机制
- 可重入锁(递归锁)
- 破坏循环等待条件
- 统一锁顺序
在 Linux 下进行多线程编程时,线程同步是至关重要的部分,尤其是在多个线程需要共享资源的场景中。尽管同步机制能够解决竞争条件,但它也带来了死锁的风险。死锁是指多个线程互相等待对方释放锁而导致永远无法继续执行的现象。为了避免死锁,可以从破坏导致死锁的四个必要条件入手。本文将从这四个条件展开,探讨如何通过破坏这些条件来避免死锁。
死锁的四个必要条件
根据操作系统中的经典理论,死锁的产生必须满足以下四个必要条件:
- 互斥条件:某些资源是只能被一个线程独占使用的。
- 持有并等待条件:一个线程已经持有了某个资源,同时它在等待获取其他线程持有的资源。
- 不可剥夺条件:已经获得的资源不能被强行剥夺,线程只能主动释放资源。
- 循环等待条件:存在一个线程循环等待的链,链中的每个线程都在等待下一个线程持有的资源。
为了避免死锁,可以通过破坏至少其中一个条件来打破死锁局面。下面,我们将详细探讨这四个条件以及如何在 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 库 ࿰…...

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…...

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

Go语言基础教程:可变参数函数
Go 语言允许函数接收可变数量的参数,这种特性对于处理数量不确定的参数特别有用。在本教程中,我们将通过示例代码讲解如何定义和使用 Go 的可变参数函数。 package mainimport "fmt"// 定义一个可变参数函数 sum,接收任意数量的整…...
高并发场景下解决并发数据不一致
简单的场景: 全量数据更新的情况下, 不在乎同一秒的请求都必须要成功, 只留下最新的更新请求数据 方案常用的是 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个学生,学号是从1→43)minValue 1maxValue 43 生成随机数(在1到43之间生成随机数)randomNumber Application.WorksheetFunctio…...

Python | Leetcode Python题解之第506题相对名次
题目: 题解: 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)
声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:安全见闻(6)_哔哩哔哩_bilibili 学无止境,开拓自己的眼界才能走的更远 本文主要讲解通讯协议涉及的安全问题。…...

Promise、async、await 、异步生成器的错误处理方案
1、Promise.all 的错误处理 Promise.all 方法接受一个 Promise 数组,并返回所有解析 Promise 的结果数组: const promise1 Promise.resolve("one"); const promise2 Promise.resolve("two");Promise.all([promise1, promise2]).…...
腾讯云:数智教育专场-学习笔记
15点13分2024年10月21日(短短5天的时间,自己的成长速度更加惊人)-开始进行“降本增效”学习模式,根据小米手环对于自己的行为模式分析(不断地寻找数据之间的关联性),每天高效记忆时间࿰…...

Ovis: 多模态大语言模型的结构化嵌入对齐
论文题目:Ovis: Structural Embedding Alignment for Multimodal Large Language Model 论文地址:https://arxiv.org/pdf/2405.20797 github地址:https://github.com/AIDC-AI/Ovis/?tabreadme-ov-file 今天,我将分享一项重要的研…...
python的Django的render_to_string函数和render函数模板的使用
一、render_to_string render_to_string 是 Django 框架中的一个便捷函数,用于将模板渲染为字符串。 render_to_string(template_name.html, context, requestNone, usingNone) template_name.html:要渲染的模板文件的名称。context:传递给…...

基于Python大数据的王者荣耀战队数据分析及可视化系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...