linux互斥锁:递归锁,非递归锁用法详解

        在实际的项目中经常涉及到共享资源,共享资源被多个线程访问会出现竞争现象;为了解决竞争和保护共享资源常用的机制之一就是互斥锁!

        互斥锁又分为递归锁和非递归锁,互斥锁默认是非递归锁,也是我们常用的上锁方式。那么什么是递归锁和非递归锁呢?

非递归锁(Non-recursive Lock)

        使用方式:非递归锁每次只能被同一个线程加锁一次,若再次尝试加锁会导致死锁。所以在使用非递归锁时,应确保同一个线程不会重复加锁。

        返回值:非递归锁的锁操作函数pthread_mutex_lock和pthread_mutex_trylock返回0表示加锁成功,非0则表示加锁失败。

示例代码:

pthread_mutex_t mutex;void* func(void){pthread_mutex_lock(&mutex);
//        pthread_mutex_lock(&mutex);//上锁之后再申请锁,这样会造成死锁std::cout<<"thread : "<<pthread_self()<<" going to get lock 2st"<<std::endl;
//        pthread_mutex_unlock(&mutex);pthread_mutex_unlock(&mutex);return NULL;
}int main(void)
{int ret = 0;pthread_t p;pthread_mutex_init(&mutex, NULL);//初始化互斥锁if((ret = pthread_create(&p, NULL, func, NULL)) != 0){fprintf(stderr, "create thread error. msg:%s", strerror(ret));exit(1);}return 0;
}

        注意:非递归锁在同一个线程中只允许申请一把锁,申请的锁被释放后才能继续申请;如果非递归锁已经被占用还没有解锁就继续申请非递归锁就会造成死锁现象。

递归锁(Recursive Lock)

        使用方式:递归锁允许同一个线程多次对锁进行加锁,只有在多次解锁之后才能真正释放锁。使用递归锁时,同一个线程重复加锁不会导致死锁。

        返回值:递归锁的锁操作函数pthread_mutex_lock和pthread_mutex_trylock返回0表示加锁成功,非0则表示加锁失败。

        示例代码:

pthread_mutex_t mutex;
pthread_mutexattr_t attr;void* func(void){pthread_mutex_lock(&mutex);pthread_mutex_lock(&mutex);//可以申请多个锁不会造成死锁std::cout<<"thread : "<<pthread_self()<<" going to get lock 2st"<<std::endl;pthread_mutex_unlock(&mutex);pthread_mutex_unlock(&mutex);return NULL;
}int main(void)
{int ret = 0;pthread_t p;if(( ret = pthread_mutexattr_init(&attr)) != 0){fprintf(stderr, "create mutex attribute error. msg:%s", strerror(ret));exit(1);}pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);pthread_mutex_init(&mutex, &attr);if((ret = pthread_create(&p, NULL, func, NULL)) != 0){fprintf(stderr, "create thread error. msg:%s", strerror(ret));exit(1);}return 0;
}

        注意:想要使用递归锁需要使用pthread_mutexattr_t 结构进行显式的属性设置,递归锁在一个线程中可以申请多把锁,但是申请锁就需要对应的释放多少锁。只有完全释放递归锁,才能被别的线程申请。

        所以,既然递归锁这么麻烦,又容易造成死锁为什么还会出现递归锁呢?

        首先明确递归锁的应用场景:嵌套函数调用,递归算法,代码重构和复用等。

        以递归函数为例:

int buf[5] = {1,2,3,4,5};void func(int val)
{if(val >= 5)return;pthread_mutex_lock(&mutex);func(buf[val++]);pthread_mutex_unlock(&mutex);//其他线程处理模块return;
}int main(void) {func(0);return 0;
}

        假设buf为共享资源,要对buf进行上锁是必然的,但是在递归函数中上锁如果使用非递归锁就会造成死锁,所以一般嵌套函数或者递归算法会使用递归锁进行临界区的保护。注意使用递归锁必须依次释放所有的锁不然会造成死锁。

        那么问题来了:那为什么不在递归算法外部:func(0)前后加锁,解锁呢?

        当然这样也可以;不过如果嵌套函数或递归算法中除了共享资源外还有其他处理,那么在最外部调用可能会延长解锁时间,导致程序效率降低;所以不同的锁要根据使用的场景决定到底使用什么锁。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零基础学Python之整合MySQL

Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 不同的数据库你需要下载不同的DB API模块&#xff0c;例如你需要访问Oracle数据库和Mysql数据&#xff0c;你需要下载Oracle和MySQL数据库模块。 DB-API 是一个规范. 它…

【51单片机】要实现动静态数码管,你首先需要知道这些【数码管项目前置知识】

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 本章节内容为【实现动静态数码管】项目的第一个模块完整章节&#xff1a;传送门 欢迎订阅 YY滴C专栏&#xff01;更多干货持…

QT styleSheet——控件设置样式表

QT开发中&#xff0c;需要设置多种多样的控件表现形式&#xff0c;QT实现的styleSheet能够满足多种多样的场景&#xff0c;这里简单的记录下一些我常用的 设置透明背景&#xff0c;鼠标悬浮时&#xff0c;设置背景色&#xff1a; pushButton->setStyleSheet("QPushBu…

Unity接入GVoice腾讯实时语音

Unity接入GVoice腾讯实时语音 一、介绍二、注册GVoice创建项目语音服务1.创建项目2.申请语音权限3.项目管理查看SDK初始化的一些参数和基本信息4.GVoice检测 三、SDK下载SDK是分为两种类型&#xff1a;独立版集成板 SDK放入Unity工程中 四、语音代码写法五、GVoice踩坑语音权限…

【canvas】获取鼠标点击位置坐标的颜色信息

在项目当中&#xff0c;要实现某业务需求例如PS魔棒功能时&#xff0c;则需要获取点击坐标的颜色信息。 功能不复杂&#xff0c;代码也很少&#xff0c;一看便知~~ 核心API为getImageData&#xff0c;传入4个参数&#xff0c;前2个为点击坐标xy&#xff0c;后2个都传1&#xf…

python调用golang中函数方法

一、原因说明&#xff1a;由于simhash方法有多种实现方式&#xff0c;现python中simhash方法与golang中的不一样&#xff0c;需要两者代码生成结果保持一致&#xff0c;故采用python中的代码调用golang编译的so文件来实现。 环境配置&#xff1a;①Windows10系统要有gcc环境&a…

ADSelfService Plus发布离线MFA功能,强化远程工作安全性

ManageEngine ADSelfService Plus推出离线多因素身份验证&#xff0c;提升远程工作安全性确保通过先进的验证方法对企业数据进行授权访问&#xff0c;无论时间、地点或连接问题如何允许远程用户安全进行身份验证&#xff0c;即使未连接到认证服务器或互联网使用高度安全的基于T…

每周编辑精选|希尔贝壳语音数据集系列上线、中国学者建立乳腺癌预后评分系统 MIRS

&#x1f3ee;新春佳节&#xff0c;归程千里为团圆 &#x1f3ee;人间烟火&#xff0c;年味浓浓阖家欢 辞别玉兔&#xff0c;金龙迎春。明晚就是大年三十除夕夜了&#xff01;HyperAI超神经在这里提前祝大家新春快乐&#xff5e;龙行龘龘(d)&#xff01;本周 hyper.ai 官网上线…

Lua协程-coroutine

lua也有协程这个机制&#xff0c;用以完成非抢占式的多任务处理。 协程与线程 协程和线程类似&#xff0c;有自己的堆栈、局部变量、指令指针等等。但同时也有不一致的地方&#xff0c;其中最重要的地方在于多线程程序可以同一时间运行多个线程&#xff0c;而协程同一时间只能…

Vue前端框架--Vue工程项目问题总结{脚手架 Vue-cli}

Vue脚手架部署问题总结 我所遇到的一共两大问题 只有先执行npm install之后 才能run serve 否则会报错 vue-cli-serve不是内部或者外部的命令&#xff0c;也不是可运行的程序或者批处理文件的错误 1. 运行npm install会报错 2. 运行npm run serve报错 nodejs官网为 https://no…

C#中实现串口通讯和网口通讯(使用SerialPort和Socket类)

仅作自己学习使用 1 准备部份 串口通讯需要两个调试软件commix和Virtual Serial Port Driver&#xff0c;分别用于监视串口和创造虚拟串口。网口通讯需要一个网口调试助手&#xff0c;网络上有很多资源&#xff0c;我在这里采用的是微软商店中的TCP/UDP网络调试助手&#xff0…

【leetcode热题100】删除排序链表中的重复元素

难度&#xff1a; 简单通过率&#xff1a; 41.5%题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目描述 给定一个排序链表&#xff0c;删除所有重复的元素&#xff0c;使得每个元素只出现一次。 示例 1: 输入: 1->1->…

cleanmymacX和腾讯柠檬哪个好用

很多小伙伴在使用Mac时&#xff0c;会遇到硬盘空间不足的情况。遇到这种情况&#xff0c;我们能做的就是清理掉一些不需要的软件或者一些占用磁盘空间较大的文件来腾出空间。我们可以借助一些专门的清理工具&#xff0c;本文中我们来推荐几款好用的Mac知名的清理软件。并且将Cl…

C语言:亲密数对

题目描述 在自然数中有一种这样的数&#xff1a;它自身是一个完全平方数&#xff0c;加上1之后是一个素数&#xff0c;这一对数被称为亲密数对&#xff0c;请编程找出指定区域内的所有亲密数对。 例如在[10,100]之间的亲密数对有&#xff1a;&#xff08;16,17&#xff09;&am…

SQL在云计算中的新角色:重新定义数据分析

文章目录 1. 云计算与数据分析的融合2. SQL在云计算中的新角色3. 分布式SQL查询引擎4. SQL-on-Hadoop解决方案5. SQL与其他数据分析工具的集成6. 实时数据分析与SQL7. SQL在云数据仓库中的角色8. 安全性与隐私保护9. SQL的未来展望《SQL数据分析实战&#xff08;第2版&#xff…

SQL笔记-2024/01/31

cross join 两个表的笛卡尔积 例如&#xff1a; select s.name student_name,s.age student_age,s.class_id class_id,c.name class_name from student s cross join class c; 子查询 select s.name name,s.score score,s.class_id class_id from student s where s.class_id …

14.scala隐式转换

目录 概述实践代码执行结果 结束 概述 隐式转换&#xff1a;偷偷的(隐式)对现有功能进行增强(转换) 实践 代码 package com.fun.scalaimport java.io.File import scala.io.Sourceobject ImplicitApp {def main(args: Array[String]): Unit {// implicit 2 to 等价 &…

vuecli3 执行 npm run build 打包命令报错:TypeError: file.split is not a function

问题 今天有个项目在打包的时候遇到了一个问题&#xff0c;就是执行 npm run build 命令的时候报错了&#xff0c;如下&#xff1a; 解决 我排查了一下&#xff0c;模拟代码如下&#xff1a;在打包的时候用了 MinChunkSizePlugin const webpack require("webpack"…

LabVIEW多任务实时测控系统

LabVIEW多任务实时测控系统 面对现代化工业生产的复杂性和多变性&#xff0c;传统的测控系统已难以满足高效、精准、可靠的监控和控制需求。因此&#xff0c;开发一种基于LabVIEW的智能测控系统&#xff0c;能够提高生产效率&#xff0c;保证生产安全&#xff0c;是解决现代工…

ubuntu 没有屏幕安装QT(SSH远程登陆下)

1背景说明 需要在SSH登陆的ubuntu远程上安装QT&#xff0c;但是远程电脑没有屏幕&#xff0c;报了这个错误“QXcbConnection: Could not connect to display”。 2网上搜索有2种解决方案 由于远程服务器没有配置屏幕&#xff0c;都失败了 2.1配置屏幕关闭 vim ~/.bashrc …