C/C++中互斥量(锁)的实现原理探究

news2024/11/26 2:34:19

互斥量的实现原理探究

文章目录

  • 互斥量的实现原理探究
    • 互斥量的概念
    • 何为原子性操作
    • 原理探究

互斥量的概念

​ 互斥量(mutex)是一种同步原语,用于保护多个线程同时访问共享数据。互斥量提供独占的、非递归的所有权语义:一个线程从成功调用locktry_lock开始,到调用unlock结束,都拥有互斥量。

何为原子性操作

程序的原子性指:整个程序中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。

原子性在一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着 “同生共死” 的感觉。在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰

如果要保证原子性,必须符合以下两条规则:

  1. 运算结果并不依赖于变量的当前值,或者能够确保只有一个线程修改变量的值。

  2. 变量不需要与其他的状态变量共同参与不变约束。

原理探究

首先给出一段加锁场景的部分代码:

void route(ThreadData *td)
{
    // 加锁
    while (true)
    {
        pthread_mutex_lock(&td->_mutex);    // 加锁
        if (td->_tickets > 0)
        {
            // 模拟一次抢票的逻辑
            usleep(1000);
            printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets);
            td->_tickets--;
            pthread_mutex_unlock(&td->_mutex); // 解锁
            td->_total++;
        }
        else
        {
            pthread_mutex_unlock(&td->_mutex); // 解锁
            break;
        }
    }
}

上面这段代码模拟了抢票逻辑,将多线程并行抢票通过锁的加入变为串行执行,有效避免了恶意数据竞争(data race)

我们不妨假定有两个线程同时执行到 加锁指令 位置:

在这里插入图片描述

(上图左侧部分为加锁和解锁对应的汇编语言代码,其中每一行简单汇编指令的执行都是原子的)

不妨设定 thread-1 先进入 lock 逻辑 (thread-2先进入同理,不影响推断):

(这里的先进入 lock 逻辑,实际上指的是先执行左侧汇编语言中 xchgb &al, mutex 语句)

这就意味着 thread-1先执行交换语句,将系统指定初始的 mutex 值 (存储在内存中) 与寄存器初始值 0 进行交换,从而寄存器中值变为1。

在这里插入图片描述

由于汇编语言简单语句的单行执行是原子的,此时thread-1 已经执行完 xchgb &al, mutex 语句,所以不排除 thread-2 紧接着也执行 xchgb &al, mutex 语句的可能。(线程被切换的时机是随时的)

这时我们需要注意:

  • CPU寄存器的硬件只有一套,但是寄存器内的数据,属于线程的硬件上下文 !
  • 数据在内存中存储时,所有线程都能访问,属于共享资源,但是当数据从内存移动到寄存器时,就属于一个线程私有了 !

当执行线程从 thread-1 变为 thread-2 时,隶属于 thread-1 的寄存器硬件上下文被取走,thread-1::%al 寄存器值为1,CPU内%al寄存器值恢复为空。

所以,当 thread-2 执行 xchgb &al, mutex 语句时,访问到寄存器内存储的内容为自身线程所属寄存器的初始值(thread-2 先前执行了 moveb $0, %al ,所以初始值为0),由于内存中 mutex 初始值1已经被 thread-1 交换取走,此时内存中 mutex 的值为0,进行交换后 %al寄存器 中的值依然为0。

经过汇编的下层判断语句 if(%al寄存器内容 > 0) 不符合条件,故 thread-2 没有成功获得锁,需要执行 goto lock 语句重新申请锁的资源。

在这里插入图片描述

综上我们可以看到,所有线程在争锁的时候,只有一个 1 !!!

至此,我们发现 thread-2 想要继续执行,就必须等待 thread-1 释放锁,所以程序的执行流程就由 thread-1 执行到释放锁结束后,将内存中 mutex 变量置为1,thread-2 才终止等待,获得 thread-1 释放的锁后,执行自身的代码逻辑。

引入锁的用途就是为了解决并发访问出现的问题,其问题的本质是多个执行流同时执行访问全局数据的代码造成的。使用锁保护全局共享资源的本质是通过保护临界区完成的。

在这里插入图片描述

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

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

相关文章

Docker管理工具Portainer忘记admin登录密码

停止Portainer容器 docker stop portainer找到portainer容器挂载信息 docker inspect portainer找到目录挂载信息 重置密码 docker run --rm -v /var/lib/docker/volumes/portainer_data/_data:/data portainer/helper-reset-password生成新的admin密码,使用新密…

flink left join消费kafka数据

left join会产生回车流数据 在控制台数据 import com.sjfood.sjfood.gmallrealtime.app.BaseSQLAPP; import com.sjfood.sjfood.gmallrealtime.util.SQLUtil; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.…

ARM32开发——库与包

🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 嵌入式软件通用架构库SPL库HAL库MSP 嵌入式软件通用架构 库 标准外设库(Standard Peripheral Library)和H…

一分钟学习数据安全——自主管理身份SSI基本概念

之前我们已经介绍过数字身份的几种模式。其中,分布式数字身份模式逐渐普及演进的结果就是自主管理身份(SSI,Self-Sovereign Identity)。当一个人能够完全拥有和控制其数字身份,而无需依赖中心化机构,这就是…

《STM32Cube高效开发教程基础篇》- 单片机知识准备

文章目录 正点原子视频P1 单片机介绍P2 Cortex-M系列介绍P3 初识STM32P4 学会查看数据手册P5 最小系统和IO分配晶振电源复位BOOT启动电路下载调试 正点原子视频 视频链接 P1 单片机介绍 P2 Cortex-M系列介绍 P3 初识STM32 P4 学会查看数据手册 P5 最小系统和IO分配 晶振 电源…

外贸怎么开发国外客户呢?

外贸开发国外客户是一个系统性的过程,需要采取多种策略来确保成功。以下是一些清晰、分点表示的方法,用于帮助外贸企业开发国外客户: 深入研究目标市场 了解目标市场的文化、商业习惯、法律法规和消费者需求。通过市场调查和分析&#xff0c…

墨天轮《2023年中国数据库行业年度分析报告》正式发布!

为明晰发展脉络,把握未来趋势,墨天轮于5月29日正式发布 《2023年中国数据库年度行业分析报告》。该报告由墨天轮联合业界专家学者共同编写,共330页,旨在梳理和洞察中国数据库行业的发展趋势、技术创新、市场动态以及面临的挑战&am…

TiKV学习5:TiDB SQL执行流程

目录 1. DML语句读流程概要 2. DML语句写流程概要 3. DDL 流程概要 4. SQL的Parse和Compile 5. 读取的执行 6. 写入的执行 7. DDL的执行 8. 小结 1. DML语句读流程概要 TiDB Server接收sql并处理,TiKV负责持久化数据,PD提供TSO和Region的数据字典…

推荐系统三十六式学习笔记:02|个性化推荐系统有哪些绕不开的经典问题?

目录 推荐系统的问题模式评分预测行为预测 几个常见顽疾1、冷启动问题2、探索与利用问题安全问题 总结 推荐系统的问题模式 推荐系统的使命是为用户和物品建立连接,建立的方式是提前找出哪些隐藏的连接呈现给用户,这是一个预测问题;所以推荐…

Echarts 实现自定义曲线的弧度

文章目录 问题分析问题 分析 在 ECharts 中,可以通过控制数据点的位置来调整曲线的弧度。具体来说,可以通过设置数据项的控制点来调整曲线的形状。ECharts 中的折线图和曲线图都是通过控制点来绘制曲线的,可以通过设置数据项的控制点来调整曲线的弧度。 以下是一个简单的示…

EG2106 原装正品 贴片SOP-8 大功率MOS管栅极驱动芯片耐压600V

EG2106 在电机控制中的应用非常广泛,下面是一些典型的应用案例: 1. 无刷直流电机(BLDC)控制:EG2106 可以用于驱动无刷直流电机的功率MOSFET或IGBT。在无刷电机控制器中,通常会用到H桥电路来控制电机的正…

你认识nginx吗,nginx是做什么的,nginx可以做什么 --2)nginx配置

hello大家今天教大家如何用nginx实验tomcat的负载均衡,同理其他的也可以,如httpd等 首先需要准备一个nginx和tomcat包,这里用到的是版本号为 然后需要准备最少三台linux虚拟机,然后我们开始吧 1.安装tomcat 解包 tar zxf /mnt/…

图数据集的加载

原文参考官方文档: https://pytorch-geometric.readthedocs.io/en/latest/modules/loader.html torch_geometric.loader 库中, 该库中包含了多种 图数据集的 加载方式, 这里主要介绍 DenseDataLoader and DataLoader 这两者之间的区别&#…

2024最新群智能优化算法:人工原生动物优化器(Artificial Protozoa Optimizer ,APO))求解23个函数,MATLAB代码

一、人工原生动物优化器 人工原生动物优化器(Artificial Protozoa Optimizer ,APO)由Xiaopeng Wang等人于2024年提出,其灵感来自自然界中的原生动物。APO 模拟了原生动物的觅食、休眠和繁殖行为。 参考文献 [1]Wang X, Snšel V…

【强化学习】DPO(Direct Preference Optimization)算法学习笔记

【强化学习】DPO(Direct Preference Optimization)算法学习笔记 RLHF与DPO的关系KL散度Bradley-Terry模型DPO算法流程参考文献 RLHF与DPO的关系 DPO(Direct Preference Optimization)和RLHF(Reinforcement Learning f…

哪款桌面便签软件安全好用?2024好用便签app推荐

桌面便签软件已经成为许多人日常生活和工作中不可或缺的工具,它们实用、灵活,能够帮助我们快速记录重要信息,提醒任务事项。随着科技的进步,市面上的便签软件层出不穷,功能也越发强大和实用。在众多的便签软件中&#…

5、css3 自动动画渐变背景

效果例图&#xff1a;&#xff08;因gif图片太大&#xff0c;而csdn只能上传小于5m图片&#xff0c;所以无法上传&#xff09; 1、首先上传html代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8">&l…

TDesign环境搭建-后台模板的安装和使用-构建web管理端后台系统

TDesign环境搭建-后台模板的安装和使用-构建web管理端后台系统 一、安装Nodejs 下载&#xff1a;nodejs 注意&#xff0c;目前前端代码使用的vue3做为脚手架进行开发&#xff0c;需要强制依赖node版本为16及以上 二、模板安装 2.1 安装脚手架&#xff1a;cli nodejs安装好之…

基于51单片机多功能防盗报警proteus仿真( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机多功能防盗报警系统 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接 基于51单片机多功能防盗报警系统( proteus仿真程序设计报告原理图讲解视频&#xff09; 仿真图proteus8.9及以上…