Linux线程安全:线程互斥

一、线程互斥的概念

1.1临界资源与互斥的关系

临界资源:多线程执行流共享的资源就叫做临界资源。
临界区:每个线程内部,访问临界资源的代码,就叫做临界区。
互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。
原子性(后面讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成。

1.2互斥量mutex

大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个线程,其他线程无法获得这种变量。
但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,可以通过数据的共享,完成线程之间的交互。
多个线程并发的操作共享变量,会带来一些问题。
以下面代码为例,创建四个线程同时进行抢票,如果多个线程同时对一个临界资源进行访问而该资源却没有被保护,就会出现bug。
// 操作共享变量会有问题的售票系统代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;
void* route(void* arg)
{char* id = (char*)arg;while (1) {if (ticket > 0) {usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;}else {break;}}
}

如上图所示,票到最后被枪成了负数而其原因就是代码中没有对临界区资源进行保护,加上临界区对临界资源的操作也并不是原子的,所以最终导致票数成了负数。

1.3汇编角度分析

取出ticket--部分的汇编代码
objdump -d a.out > test.objdump
152 40064b: 8b 05 e3 04 20 00 mov 0x2004e3(%rip),%eax # 600b34 <ticket>
153 400651: 83 e8 01 sub $0x1,%eax
154 400654: 89 05 da 04 20 00 mov %eax,0x2004da(%rip) # 600b34 <ticket>
-- 操作并不是原子操作,而是对应三条汇编指令:
load :将共享变量ticket从内存加载到寄存器中
update : 更新寄存器里面的值,执行-1操作
store :将新值,从寄存器写回共享变量ticket的内存地址。
而线程是随时都有可能被切换的,依照如上代码的逻辑,临界区的操作并不是原子的,CPU先将ticket从内存中取出来放到寄存器中,然后对其进行减法操作,最后再将其放回到内存当中,其中任何一步都有可能导致线程带着上下文数据被切出而内存中ticket的值依然没有改变,导致其他线程进行访问操作时依然拿到的是未被改变的ticket值,然后继续往下执行,而另一个线程此时又将更改过的ticket放回到内存中,此时就会导致tickt的值比规定的下限值要低。
要解决以上问题,需要做到三点:
1.代码必须要有互斥行为:当代码进入临界区执行时,不允许其他线程进入该临界区。
2.如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许一个线程进入该临界区。
3.如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区。
要做到这三点,本质上就是需要一把锁。 Linux 上提供的这把锁叫互斥量。

二、互斥量(锁)的接口

2.1初始化互斥量

初始化互斥量有两种方法:
加锁本质上就是将并行执行变为串行执行。
方法1,静态分配:
如果要定义一把静态的锁,或者是全局的锁,直接定义一个pthread_mutex_t类型的变量,然后通过PTHREAD_MUTEX_INITIALIZER进行初始化就可以使用锁。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
方法2,动态分配:
如果要定义一把局部的锁,就需要进行手动的初始化以及销毁。
int pthread_mutex_init(pthread_mutex_t* restrict mutex,const pthread_mutexattr_t* restrict attr);
参数:
mutex:要初始化的互斥量
attr:NULL

2.2申请及使用锁

加锁

int pthread_mutex_lock(pthread_mutex_t *mutex);

申请锁会出现以下几种状态:

1、申请成功:函数就会返回,允许继续运行。

2、申请失败:函数就会阻塞,不允许继续往下执行。

3、函数调用失败,出错返回。

解锁

int pthread_mutex_unlock(pthread_mutex_t *mutex);

尝试申请锁

int pthread_mutex_trylock(pthread_mutex_t *mutex);

三、互斥量实现原理

经过上面的例子,大家已经意识到单纯的 i++ 或者 ++i 都不是原子的,有可能会有数据一致性问题
为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的 总线周期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。 现在我们把lock和unlock的伪代码改一下。
int ticket = 100;
pthread_mutex_t mutex;
void* route(void* arg)
{char* id = (char*)arg;while (1) {pthread_mutex_lock(&mutex);if (ticket > 0) {usleep(1000);printf("%s sells ticket:%d\n", id, ticket);ticket--;pthread_mutex_unlock(&mutex);// sched_yield(); 放弃CPU}else {pthread_mutex_unlock(&mutex);break;}}
}

 通俗来讲:调用锁以后,CPU内会存在一个al寄存器内部存储一个0,在申请锁时,内存中存在mutex内部为1,在一个线程调用锁时,CPU会将al和mutex中的值直接交换,如果此时al为1则说明申请成功,而该线程被中断后会将CPU寄存器中自己的上下文数据全部带走,此时al和mutex中都是0,当下一个线程申请锁时,al交换到的mutex中的内容还是0,此时就只能挂起等待别的线程将锁归还。

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

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

相关文章

《数字图像处理-OpenCV/Python》第15章:图像分割

《数字图像处理-OpenCV/Python》第15章&#xff1a;图像分割 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第15章&#xff1a;图像分割 图像分割是由图像处理到图像分析的关键步骤…

对 SQL 说“不”~

开发人员注意&#xff01; 您在当前的应用程序架构中是否面临这些问题&#xff1f; 对 SQL 数据库的高吞吐量。SQL 数据库中的瓶颈。 内存数据存储将是解决问题的方案。Redis 是市场上最受欢迎的内存数据存储和缓存选项。Redis 拥有广泛的生态系统&#xff0c;因为主要科技巨…

54.WEB渗透测试-信息收集- 端口、目录扫描、源码泄露(2)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;53.WEB渗透测试-信息收集-端口、目录扫描、源码泄露&#xff08;1&#xff09; 关于源码…

Nginx作为下载站点

grep -Ev ^$|# /usr/local/nginx/conf/nginx.conf > /opt/nginx.txt cat /opt/nginx.txt > /usr/local/nginx/conf/nginx.conf用上面的指令提取最小化的配置文件 vim /usr/local/nginx/conf/nginx.conf [rootlocalhost ~]# cat /usr/local/nginx/conf/nginx.conf worker…

解决linux系统求前N月月份的bug

日常工作中&#xff0c;需要获取某个日期&#xff08;20240531&#xff09;的前N个月&#xff0c;通常会写命令 date -d "20240531 last-month" %Y%m 我期望得到202404 但是很意外&#xff1a; 经过几轮测试&#xff0c;发现只要月内天数超过30天&#xff0c;即所有…

短视频动画脚本:成都鼎茂宏升文化传媒公司

短视频动画脚本&#xff1a;创作与魅力的探索 在数字化时代的浪潮中&#xff0c;短视频动画以其独特的魅力迅速崛起&#xff0c;成为大众娱乐和信息传播的重要载体。成都鼎茂宏升文化传媒公司作为一名原创文章编辑&#xff0c;我深入探索了短视频动画脚本的创作过程&#xff0…

二,几何相交-5,BO算法分析--(1)正确性

也就是说&#xff0c;BO算法有没有可能误报或者漏报&#xff1f; 一&#xff0c;为什么不会误报&#xff1f; 因为两条线段从不相邻到相邻&#xff0c;或者其中一条线段不存在到相邻&#xff0c;都会进行一次相交测试。所以不会误报。 二&#xff0c;为什么不会漏报&#xff1…

学习算法笔记(7.5)-贪心算法(股票售卖问题)

学到这里的大家应该都非常清楚贪心算法到底是怎么一回事了&#xff0c;说白了就是动态规划的一种特例&#xff0c;没有动态规划的使用范围广&#xff0c;但是效率却比动态规划效率高&#xff0c;贪心算法不考虑之前的情况&#xff0c;只考虑当前的最优选择以期达到最优的结果。…

五款效率软件助你事半功倍

1、&#x1f517; 亿可达 作为一款自动化工具&#xff0c;亿可达被誉为国内版的免费Zaiper。它允许用户无需编程知识即可将不同软件连接起来&#xff0c;构建自动化的工作流程。其界面设计清新且直观&#xff0c;描述语言简洁易懂&#xff0c;使得用户可以轻松上手。 2、&…

轻松产出创新点!多元时间序列最新可参考成果,高性能高精度

今天给大家推荐一个好挖创新点的研究方向&#xff1a;多元时间序列。 多元时间序列是我们解决复杂系统分析和预测问题的重要工具。它通过综合分析多个相关时序数据&#xff0c;可以给我们提供更精准的预测结果&#xff0c;非常适合处理涉及多个变量和多个时间点数据的场景&…

基于 GhostNet 不同版本的图像识别

1、介绍 GhostNet 文章地址&#xff1a;[1911.11907] GhostNet: More Features from Cheap Operations (arxiv.org) 主要思想&#xff1a; 特征提取的时候&#xff0c;很多特征图是具有高度相似性的&#xff0c;也就是说存在许多的冗余特征图。 从另一个角度想&#xff0c;…

从零开始实现自己的串口调试助手(5) -实现HEX显示/发送/接收

实现HEX显示: HEX 显示 -- 其实就是 十六进制显示 --> a - 97(10) --> 61(16) 添加槽函数(bool): 实现槽函数: 注意: 注意QString 没有处理HEX显示的相关API 需要使用 toUtf-8 来 转换位QByteArry 类型&#xff0c; 利用其中的API 来处理HEX格式(toHex fromHex) vo…

Kubernetes外部服务管理Ingress介绍

前言 在 Kubernetes 集群中&#xff0c;管理外部服务的访问和流量路由至关重要。通过使用 Ingress 控制器&#xff0c;我们能够实现对外部服务的有效管理&#xff0c;配置灵活的路由规则&#xff0c;并实现负载均衡和流量控制。 目录 一、Ingress 介绍 1. Ingress 概述 2.…

Windows下搭建Cmake编译环境进行C/C++文件的编译

文章目录 1.下载Cmake2.安装MinGW-w643.进行C/C文件的编译 1.下载Cmake 网址&#xff1a;https://cmake.org/download/ 下载完成后安装&#xff0c;勾选“Add CMake to the system PATH for the current user" 点击Finish完成安装&#xff0c;在cmd窗口验证一下是否安…

C++并发之线程(std::thread)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 get_id3.4 joinable3.5 join3.6 detach3.7 swap3.8 hardware_concurrency 1 概述 Thread类来表示执行的各个线程。   执行线程是指可以在多线程环境中与其他此类序列同时执行的指令序列&#xff0c;同时共享相同…

python使用pandas的常用操作

文章目录 安装导入主要数据结构常用方法和操作创建数据结构读取和写入数据数据选择和过滤数据操作基本统计分析分组和聚合合并和连接重塑数据1. pivot 和 pivot_table2. melt3. stack和 unstack 常用方法总结pandas操作excel安装相关库 读取单个工作表读取指定工作表读取多个工…

短视频矩阵系统源码---开发BS架构B/S(Browser/Server Architecture)架构

短视频矩阵系统源头开发------- 第一款叫做筷子科技&#xff0c;这个筷子科技剪辑和发布都是没有问题的&#xff0c;但是前一段时间他的剪辑发个公告&#xff0c;每个账号只能发两条&#xff0c;另外它的唯一缺点就是它成本比较高的&#xff0c;入门门槛应该在12800左右&#…

CHATGPT升级plus(已有账号前提下)

注册wildcard(虚拟卡) 注册号账号后先进行充值&#xff0c;充值后选择CHATGPT一键升级按照他的流程来即可 Wildcard网址&#xff1a;Wildcard跳转注册 填写邀请码充值时少两美金合计14&#xffe5; 邀请码&#xff1a;OL3QXTRH

【2022-2011年】地级市数字经济指数原始数据+测算dofile+结果

参照赵涛等&#xff08;2020&#xff09;的文章&#xff0c;利用熵值法对城市数字经济指数进行测算&#xff0c;包括原始数据、线性插值、回归填补3种版本下测算的数字经济指数。保留原始数据、stata代码和测算结果&#xff0c;大家可进行复现 一、数据介绍 数据名称&#x…