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

死锁检测组件-设想

死锁检测组件-设想

现在有三个临界资源和三把锁绑定了,三把锁又分别被三个线程占用。(不用关注临界资源,因为锁和临界资源是绑定的)

20230217203523

但现在出现这种情况:线程1去申请获取锁2,线程2申请获取锁3,线程3申请获取锁1,这样就会造成死锁:

20230215224714

死锁问题,可转换为有向图的环路检测

死锁的构建

有四个线程,4把锁,以下代码一定会产生死锁


pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx4 = PTHREAD_MUTEX_INITIALIZER;void *thread_routine_a(void *arg) {printf("thread_routine a \n");pthread_mutex_lock(&mtx1);sleep(1);	pthread_mutex_lock(&mtx2);pthread_mutex_unlock(&mtx2);pthread_mutex_unlock(&mtx1);printf("thread_routine a exit\n");}void *thread_routine_b(void *arg) {printf("thread_routine b \n");pthread_mutex_lock(&mtx2);sleep(1);pthread_mutex_lock(&mtx3);pthread_mutex_unlock(&mtx3);pthread_mutex_unlock(&mtx2);printf("thread_routine b exit \n");
// -----pthread_mutex_lock(&mtx1);
}void *thread_routine_c(void *arg) {printf("thread_routine c \n");pthread_mutex_lock(&mtx3);sleep(1);pthread_mutex_lock(&mtx4);pthread_mutex_unlock(&mtx4);pthread_mutex_unlock(&mtx3);printf("thread_routine c exit \n");
}void *thread_routine_d(void *arg) {printf("thread_routine d \n");pthread_mutex_lock(&mtx4);sleep(1);pthread_mutex_lock(&mtx1);pthread_mutex_unlock(&mtx1);pthread_mutex_unlock(&mtx4);printf("thread_routine d exit \n");
}int main() {
#if 1init_hook();pthread_t tid1, tid2, tid3, tid4;pthread_create(&tid1, NULL, thread_routine_a, NULL);pthread_create(&tid2, NULL, thread_routine_b, NULL);pthread_create(&tid3, NULL, thread_routine_c, NULL);pthread_create(&tid4, NULL, thread_routine_d, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);pthread_join(tid4, NULL);
}

这里产生了:线程a => 线程b => 线程c => 线程d =》 线程a的这样一个环路

但是我们不知道哪把锁被哪个线程占用了,没法构建有向图,也就无法得知是否产生了这样一个环路

这时,可以用hook,调自己写的 pthread_mutex_lock,将线程和锁的映射关系保存起来

pthread的hook

有点像装饰器模式

// 函数指针
typedef int (*pthread_mutex_lock_t)(pthread_mutex_t *mutex);
pthread_mutex_lock_t pthread_mutex_lock_f;typedef int (*pthread_mutex_unlock_t)(pthread_mutex_t *mutex);
pthread_mutex_unlock_t pthread_mutex_unlock_f;static int init_hook() {//  RTLD_NEXT可以理解为代码段,在这里面找pthread_mutex_lock函数名,把地址返回// 所以pthread_mutex_lock_f就是静态或动态库里的pthread_mutex_lock锁函数  pthread_mutex_lock_f = dlsym(RTLD_NEXT, "pthread_mutex_lock"); pthread_mutex_unlock_f = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
}int pthread_mutex_lock(pthread_mutex_t *mutex) {printf("pthread_mutex_lock selfid %ld, mutex: %p\n", pthread_self(), mutex);beforelock(pthread_self(), mutex);pthread_mutex_lock_f(mutex);    // 用钩子的好处,给系统函数命一个别名afterlock(pthread_self(), mutex);}int pthread_mutex_unlock(pthread_mutex_t *mutex) {printf("pthread_mutex_unlock\n");pthread_mutex_unlock_f(mutex);afterunlock(pthread_self(), mutex);}

这样,在加锁的时候,就能知道锁id(mutex)和线程id的对应关系

图的构建

通过邻接表实现有向图,如:线程1等待线程2释放锁,则将线程id2挂到线程1后面

20230216225923

而如何知道线程1申请的锁被线程2占用了呢:设置一个 mutex 和 thread的映射列表(结构体数组),通过mutex返回threadid。

如线程1对mutex1加锁,将(mutex1,threadid1)加入locklist中,表示mutex1被线程1占用了

图的邻接表生成:当前线程根据要申请的mutex a找到占用这把锁的线程id A(通过映射列表),将改线程追加到自己的后面

通过邻接表检测环路:DFS,检测过的标为1,再遇到一个1就表示死锁了

20230216230719

那我们怎么把这个图构建起来: 通过三个原语操作
beforelock、afterlock、afterrunlock 以后要用到再说吧

至此,死锁检测组件设计的大致思路为:通过hook保存muitex和threadid的映射关系,根据这个映射关系生成线程之间的有向图(邻接表),再利用dfs检测图的环路

相关文章:

死锁检测组件-设想

死锁检测组件-设想 现在有三个临界资源和三把锁绑定了,三把锁又分别被三个线程占用。(不用关注临界资源,因为锁和临界资源是绑定的) 但现在出现这种情况:线程1去申请获取锁2,线程2申请获取锁3,…...

线程池的使用

为什么要使用线程池 复习一下创建线程的几种方式: 继承Thread 实现Runnable 实现Callable 但是如果频繁的创建/销毁线程,就会造成资源浪费。这时候就需要将线程创建好之后存起来,以后要用取出来,用完后再放回去。 注意 &#xff…...

字节码指令

目录 2.1 入门 2.2 javap 工具 2.3 图解方法执行流程 1)原始 java 代码 2)编译后的字节码文件 3)常量池载入运行时常量池 4)方法字节码载入方法区 5)main 线程开始运行,分配栈帧内存 6)…...

TLS/SSL证书彻底扫盲

证书格式 pem Privacy Enhanced Mail文本格式,以 -----BEGIN CERTIFICATE----- 开头,以-----END CERTIFICATE-----结尾 der 二进制格式,只保存证书,不保存私钥java和window服务器常见 pfx/p12 Predecessor of PKCS#12二进制格式&…...

WGCNA | 值得你深入学习的生信分析方法!~(网状分析-第五步-高级可视化)

1写在前面 前面我们用WGCNA分析完成了一系列的分析,聚类分割模块。🥰 随后进一步筛选,找到与我们感兴趣的表型或者临床特征相关的模块,而且进行了模块内部分析。😘 再然后是对感兴趣模块进行功能注释,了解模…...

try catch finally执行顺序

try catch finally,try里有return,finally还执行么?答案: 执行,并且返回return时,finally的执行早于try。try-catch-finally的执行顺序无return当try中的t()没有抛出异常public static void main(String[] …...

2023年数学建模美赛D题(Prioritizing the UN Sustainability Goals)分析与编程

2023年数学建模美赛D题分析建模与编程 重要说明: 本文介绍2023年美赛题目,并进行简单分析;本文首先对 D题进行深入分析,其它题目分析详见专题讨论;本文及专题分析将在 2月17日每3小时更新一次,完全免费&am…...

35岁测试工程师被辞退,给你们一个忠告

一:前言:人生的十字路口静坐反思 入软件测试这一行至今已经10年多,承蒙领导们的照顾与重用,同事的支持与信任,我的职业发展算是相对较好,从入行到各类测试技术岗位,再到测试总监,再转…...

华为OD机试题 - 租车骑绿岛(JavaScript)

最近更新的博客 2023新华为OD机试题 - 斗地主(JavaScript)2023新华为OD机试题 - 箱子之形摆放(JavaScript)2023新华为OD机试题 - 考古学家(JavaScript)2023新华为OD机试题 - 相同数字的积木游戏 1(JavaScript)2023新华为OD机试题 - 最多等和不相交连续子序列(JavaScri…...

Linux下Python脚本的编写解析fio(minimal格式)(三)

在服务器测试(storage)过程中,会看到很多人写跑fio的脚本用minimal格式来解析,因为这种格式返回的结果对与脚本(shell,python)解析log非常方便.下面介绍一下这种方式下,用Python来解析log 1 一般客户会要求结果中出现一下参数的值: bandwidth…...

【实战场景二】如何设计一个分布式锁?

如何优雅的设计一个分布式锁?如何设计一个分布式锁?1、什么是分布式锁2、那么分布式锁,具备什么条件呢?3、设计分布式锁有哪些方式?3.1 利用redis实现分布式锁原理3.2 基于数据库做分布式锁3.3 基于zookeeper实现分布式…...

Java中ThreadLocal类详解

ThreadLocal从名字上我们看出,它叫做本地线程变量,每个线程都有各自的的变量,而不再是我们之前的两个线程共用同一个变量;以这个类创建的变量,在多个线程都用到这个变量时,可以为每一个线程创建一个变量副本…...

从一致性角度考虑推荐冷启动长尾推荐问题(一)

前言:目前中长尾推荐的方法有很多,主流的方法有几类比如:1)在没有项目ID嵌入的情况下提高推荐模型的鲁棒性,2)利用有限的交互数据提高学习效率,如使用元学习方法;3)利用物品侧面信息,便于物品ID嵌入的初始化&#xff0…...

电脑(Windows)常用快捷键

简述:实用的键盘快捷键是一个程序员的必备技能,下面给大家整理了一下常用的键盘快捷键; ⭐CtrlP 打开“打印机”对话框; ⭐CtrlW 关闭当前网页; ⭐CtrlF 查找(网页内查找); ⭐…...

Java类加载器

1 类加载器 1.1 类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为…...

信号完整性设计规则之单根信号失真最小化

本文内容从《信号完整性与电源完整性分析》整理而来,加入了自己的理解,如有错误,欢迎批评指正。 1. 通常采用所能容许的最长上升边。 上升边越短,带宽越大,信号完整性问题越严重。 2. 使用可控阻抗走线。 可控阻抗…...

Python3 数据结构

列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能。 以下是 Python 中列表的方法: 方法 描述 list.append(x) 把一个元素添加到列表的结尾&#xf…...

Compose-Navigation带参传递

带参传递 目前 compose 还不支持传入对象作为参数! 简单双参数 根目录下新建文件夹 entity,新建单例类 ContentType 作为数据类存储位置 新增数据类 DemoContent,这表示我们需要传入的两个参数,后面带问号判空 object ContentT…...

【函数栈帧的创建和销毁】 -- 神仙级别底层原理,你学会了吗?

文章目录1.函数的调用方式 2.函数在栈区上的动作 1.函数的调用方式 相信你对调用函数一点都不陌生,但是在调用函数的过程中,却存在着很多你无法见到的东西,这是底层信息,想要理解透彻,就得深入底层去观察。 本文以…...

Promise的使用及原理

此文章主要讲解核心思想和基本用法,想要了解更多细节全面的使用方式,请阅读官方API 这篇文章假定你具备最基本的异步编程知识,例如知道什么是回调,知道什么是链式调用,同时具备最基本的单词量,例如page、us…...

ANPC逆变器下垂控制的“阻抗相消术

ANPC-下垂功率均分-两台ANPC三电平逆变器在不同阻感性线路阻抗下实现有功均分与无功均分,采用积分改进法(阻抗相消法),电压电流双闭环控制,中点电位平衡控制,SPWM调制。 1.下垂,电压电流双闭环控…...

JeecgBoot低代码开发平台终极实战指南:从零开始构建企业级应用

JeecgBoot低代码开发平台终极实战指南:从零开始构建企业级应用 【免费下载链接】jeecg-boot jeecgboot/jeecg-boot 是一个基于 Spring Boot 的 Java 框架,用于快速开发企业级应用。适合在 Java 应用开发中使用,提高开发效率和代码质量。特点是…...

革命性AI身份系统:Second Me如何重新定义数字分身技术

革命性AI身份系统:Second Me如何重新定义数字分身技术 【免费下载链接】Second-Me 开源 AI 身份系统,通过本地训练和部署,模仿用户思维和学习风格,创建专属AI替身,保护隐私安全。 项目地址: https://gitcode.com/gh_…...

科哥CAM++镜像入门指南:快速搭建中文语音识别系统

CAM镜像入门指南:快速搭建中文语音识别系统 1. 系统概述 CAM说话人识别系统是一个基于深度学习的声纹识别工具,由科哥封装为易用的Docker镜像。它能快速判断两段语音是否来自同一说话人,并提取语音特征向量,适用于身份验证、语音…...

C++vector,智能指针,拷贝构造函数

我将分别介绍 C 中的智能指针、std::vector 动态数组以及拷贝构造函数的概念、用法和适用场景。一、C 智能指针智能指针是用于自动化管理动态分配内存的模板类&#xff0c;位于 <memory> 头文件中。它们通过 RAII&#xff08;Resource Acquisition Is Initialization&…...

跨平台终端工具cmatrix:打造震撼的数字雨可视化效果

跨平台终端工具cmatrix&#xff1a;打造震撼的数字雨可视化效果 【免费下载链接】cmatrix Terminal based "The Matrix" like implementation 项目地址: https://gitcode.com/gh_mirrors/cm/cmatrix 你是否曾幻想过在自己的终端中重现《黑客帝国》里令人着迷的…...

阅读书源校验工具verifyBookSource v2.0避坑指南:如何避免无效书源和重复书源

verifyBookSource v2.0 高效书源管理实战&#xff1a;从校验到优化的完整指南 在数字阅读日益普及的今天&#xff0c;一个优质的书源库能显著提升阅读体验。然而&#xff0c;面对海量书源&#xff0c;如何快速筛选有效内容、剔除重复资源&#xff0c;成为许多阅读爱好者的痛点。…...

ICML 2026 开分!投稿群来了!还有IJCAI、CVPR 2026投稿群!

点击下方卡片&#xff0c;关注“CVer”公众号AI/CV重磅干货&#xff0c;第一时间送达点击进入—>【顶会/顶刊】投稿交流群添加微信&#xff1a;CVer2233&#xff0c;助手会拉你进群&#xff01;扫描下方二维码&#xff0c;加入CVer学术星球&#xff01;可获得最新顶会/顶刊上…...

Ubuntu 18.04双网卡实战:5分钟搞定内网穿透+NAT转发(含DHCP自动分配)

Ubuntu 18.04双网卡配置全指南&#xff1a;从内网穿透到自动化管理 在实验室环境或小型办公网络中&#xff0c;经常需要一台主机同时连接内外网。Ubuntu 18.04作为长期支持版本&#xff0c;其网络功能稳定可靠&#xff0c;特别适合作为网关设备。本文将手把手教你如何配置双网卡…...

云容笔谈·东方红颜影像生成系统与ComfyUI工作流集成:可视化节点式创作

云容笔谈东方红颜影像生成系统与ComfyUI工作流集成&#xff1a;可视化节点式创作 如果你是一位数字艺术家或者技术美术&#xff0c;可能常常面临这样的困境&#xff1a;你有一个绝佳的创意&#xff0c;比如想生成一幅融合了东方古典美学与现代光影的“红颜”肖像&#xff0c;但…...