Linux——什么是互斥与互斥锁

news2024/11/15 19:35:06

目录

一.前提:临界区 & 临界资源

二.什么是互斥

(一).互斥概念

(二).为什么需要互斥

三.互斥锁介绍

(一).互斥锁的概念

(二).互斥锁的使用

①系统API接口

②C++库

(三).互斥锁的底层原理

①加锁

②解锁


一.前提:临界区 & 临界资源

编写多线程程序时,多个线程可能需要执行同一个函数。如果该函数中有变量为这些线程共享,且可以改变,这样的变量可以称为临界资源

相对应的改变这些资源的代码就叫做临界区

示例如下代码:

int i = 0;//变量i为这些线程共享,即临界资源
void* func(void* arg){
    ...
    //临界区起点
    i = 3;
    //临界区终点
    ...
}

int main(){
    pthread_t tid[2];
    pthread_create(&tid[0], nullptr, func, nullptr);
    pthread_create(&tid[1], nullptr, func, nullptr);
    pthread_join(tid[0], nullptr);
    pthread_join(tid[1], nullptr);
    return 0;
}

二.什么是互斥

(一).互斥概念

所谓互斥,其实就是在某一时刻只能有一个线程访问临界区,且完整的使用临界资源没有其他线程打扰,即原子性

简单来说就是当前线程使用完临界资源后其他线程才能来使用。

(二).为什么需要互斥

如果多个线程同时访问临界资源,那么可能造成很严重的后果。

举个例子:
如下代码:

std::cout >> i >> std::endl;
i--;

假设此时i == 1,当有多个线程同时执行时,可能会发生意向不到的情况。 

进行i--操作时,CPU其实分为三个步骤:

 当线程A执行i--时,如果在②步骤执行完毕后被操作系统突然切换为线程B,那么i值不会写回内存,而是作为上下文数据被该线程携带:

当线程B执行i--时,①步骤从内存中读取的是1之后②③步骤正常执行完毕,写回内存中,此时内存i值为0: 

如果此时再将线程A切回,那么会直接执行③步骤,也就是说会将内存值写为0,而这就与程序不符了。

明明是被两个线程执行过,i应该是-1,而结果却是0!

因此,当多线程使用临界区时,要确保只能有一个线程访问该临界资源,且必须是原子性的使用资源。

换一种说法就是,如果没有互斥保护,那么多线程访问临界资源就是并发执行;当有互斥保护时,多线程问临界资源就是串行执行

三.互斥锁介绍

(一).互斥锁的概念

互斥锁通俗来讲就是用来完成互斥行为的对象,锁住的范围一般就是临界区。

需要互斥操作的多线程共享一个互斥锁,当一个线程获得互斥锁后,其他线程会阻塞等待,直到当前线程归还互斥锁后,其他线程争抢互斥锁,谁获得了谁能进入临界区执行代码。

(二).互斥锁的使用

①系统API接口

头文件<pthread.h>

定义

pthread_mutex_t mtx;

初始化(两种方式):

pthread_mutex_init(&mtx, nullptr);//方式一
pthread_mutex_t mtx = PTHREAD_MUTEX_INITALIZER;//方式二

 加锁与解锁

lock与trylock的区别是,当多线程同时争抢互斥锁时,lock会让未抢到的线程阻塞等待,trylock不会阻塞等待

pthread_mutex_lock(&mtx);
...//临界区
pthread_mutex_unlock(&mtx);

 销毁

pthread_mutex_destroy(&mtx);

②C++库

头文件<mutex>

定义互斥锁对象

std::mutex mtx;

加锁与解锁

mtx.lock();//方式一,阻塞等待
mtx.try_lock();//方式二,非阻塞等待
...//临界区
mtx.unlock();

(三).互斥锁的底层原理

 底层汇编:

①加锁

1.

这一步是将0值写入al寄存器中。

图示:

2.

将al寄存器值与mutex值(即互斥量)交换,无锁时mutex值是1。

图示:

3.

如果al值大于0,即该线程获得锁,那么返回。如果没有获取锁,线程会阻塞,阻塞结束后跳转重新执行加锁过程。

图示:

对于线程B而言,当被调用后使用CPU时,此时mutex中值为0,al先被赋值为0,与mutex交换后值依旧为0,因此,当执行第三步时,会判断为else的情况,即阻塞等待。当线程A执行完毕解锁后,再经过goto语句,重新执行加锁过程。

总之,所谓加锁,其实就是所有线程抢占一个互斥量(1),抢到的给al寄存器,加锁成功;没抢到的,al寄存器值为0,阻塞等待。

②解锁

相对于加锁,解锁很简单,就是当线程执行完临界区后,将mutex中的值置为1即可。

这样,当其他线程抢锁时,mutex值为1,总会有一个线程加锁成功。

图示如下:


如有错误,敬请斧正 

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

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

相关文章

内网服务器结合vxlan和iptables-snat实现内网服务器公网访问——筑梦之路

之前通过其他方式实现 CentOS搭建NAT和DHCP服务&#xff0c;实现共享上网_筑梦之路的博客-CSDN博客_vsphere 创建dhcp CentOS 7 firewalld实现共享上网和搭建本地yum仓库——筑梦之路_筑梦之路的博客-CSDN博客 如上图&#xff0c;有这样一种场景&#xff0c;我们经常遇到&am…

推荐和搜索系统的多样性研究综述

前言 检索结果的多样化是检索系统的一个重要研究课题&#xff0c;其可以满足用户的各种兴趣和供应商的平等公平曝光。 然而&#xff0c;检索系统中&#xff08;搜索与推荐领域&#xff09;的多样性研究缺乏一个系统的汇总&#xff0c;并且研究点相对零散。本次介绍的paper中&am…

深度学习可视化工具:Netron

Netron是一个用于神经网络、深度学习和机器学习模型的可视化工具。 Netron支持 ONNX、TensorFlow Lite、Caffe、Keras、Darknet、PaddlePaddle、ncnn、MNN、Core ML、RKNN、MXNet、MindSpore Lite、TNN、Barracuda、Tengine、CNTK、TensorFlow.js、Caffe2 和 UFF。 它还实验性…

[PyTorch]在PyTorch环境下使用Tensorboard

一、配置环境 在控制台中使用pip install语句安装Tensorboard&#xff08;同时需要安装tensorflow&#xff09; pip install tensorflow pip install tensorboard 添加引用并为其设置路径 from torch.utils.tensorboard import SummaryWriterwriter SummaryWriter(log_dir 日…

3轴数字罗盘IC HMC5883L介绍

3轴数字罗盘IC HMC5883L简介霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块&#xff0c;并带有数字接口的弱磁传感器芯片&#xff0c;应用于低成本罗盘和磁场检测领域。HMC5883L 包括最先进的高分辨率HMC118X 系列磁阻传感器&#xff0c;并附带霍尼韦尔专利的集成电路包括放大器…

Rstudio连接不上R语言常用解决方案

Rstudio链接不上R语言&#xff0c;默认情况下是不应该发生的&#xff0c;既然发生了&#xff0c;肯定是有些条件没有满足&#xff0c;如果将下面几个条件都满足&#xff0c;应该可以解决这个问题。 1. R和Rstudio安装路径为中文 虽然R和Rstudio支持中文&#xff0c;但是如果安…

干货 | 金融大数据风控利用个人信息的边界

以下内容整理自清华大学《数智安全与标准化》课程大作业期末报告同学的汇报内容。第一部分&#xff1a;大数据风控技术及应用现状在人民币贷款持续增长&#xff0c;市场环境日趋复杂的情况下&#xff0c;利用大数据进行风控是社会主义市场经济进行金融资源合理配置不可或缺的手…

jmeter做接口和自动化常见的使用方法

目录一、提取器1.JSON 提取器的应用场景1.1.提取某个特定值1.1.1.切片提取获取某个位标值1.2.提取多个值1.3.按条件查询按1.3.1.件提取是一个常用的方法1.3.2.还有其余几种用法1.4.提取值组成的列表2. 正则 提取器的应用场景二、CSV 参数化三、beanShell 脚本1.beanShell 引用变…

基于python inference 、ResNet实现的图像分类 (附完整代码可作为毕设参考)

这篇文章主要介绍了 图像分类的 inference,其中会着重介绍 ResNet。 2.模型概览 在torchvision.model中,有很多封装好的模型。 可以分类 3 类:

typecho去掉index.php

typecho去掉index.php一、前言二、配置过程三、问题所在四、解决方案五、一点体会一、前言 大家好&#xff0c;我是尝试中成长的站长&#xff0c;最近在使用typecho的过程中遇到了这种问题&#xff0c;index.php的伪静态没办法去掉&#xff0c;遂浏览器搜索了很多教程&#xf…

Jetpack架构组件库:WorkManager

WorkManager WorkManager 是Android最新一代的后台调度 API&#xff0c;主要是用来替换先前的旧版后台调度 API&#xff08;如 JobScheduler 等&#xff09;。 WorkManager 是适合用于持久性工作的推荐解决方案。如果工作始终要通过应用重启和系统重新启动来调度&#xff0c;…

无线局域网接入

非法接人是指非授权终端与无线局域网中的接入点&#xff08;Access Point&#xff0c;AP&#xff09;之间建立关联的过程&#xff0c;非法接入使得非授权终端可以与无线局域网中的授权终端交换数据&#xff0c;并可以通过AP访问网络资源。 非法登录是指非授权用户远程登录网络…

【JavaEE初阶】第八节.多线程(基础篇)阻塞队列(案例二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、阻塞队列概论 1.1 阻塞队列的概念与作用 1.2 阻塞队列的应用场景 —— 生产者消费者模型 1.3 生产者消费者模型的好处 二、阻塞队列的实现 2.1 Java标准库里面…

java中常见API该如何使用?

目录 API(Application Programming Interface)概述 如何使用API&#xff1f; API(Application Programming Interface)概述 –应用程序编程接口 –编写一个机器人程序去控制机器人踢足球&#xff0c;程序就需要向机器人发出向前跑、向后跑、射门、抢球等各种命令&#xff0c…

SECURECRT全局日志文件设置

SecureCRT配置自动记录日志很多人用SecureCRT时&#xff0c;希望自动记录日志&#xff0c;一个是方便以后查阅&#xff0c;一个是对自己的操作有个记录。可以看看自己做了什么操作&#xff0c;有时甚至可以看看之前是不是犯了什么错&#xff0c;是个很不错的功能。设置很简单&a…

[数据库迁移]-ES集群的部署

[数据库迁移]-ES集群的部署 森格 | 2023年1月 上一篇文件我们已经把Linux系统的LVM逻辑卷完成了&#xff0c;那下面我们就该把es集群环境搭建起来了&#xff0c;主要是以shell脚本来进行一键部署。 上文回顾&#xff1a;[数据库迁移]-LVM逻辑卷管理 一、环境介绍 1.1 环境配…

微分先行PID控制算法及仿真

微分先行PID控制的结构如图1所示&#xff0c;其特点是只对输出量y(k)进行微分&#xff0c;而对给定值y(k)不作微分。这样&#xff0c;在改变给定值时&#xff0c;输出不会改变&#xff0c;而被控量的变化通常是比较缓和的。这种输出量先行微分控制适用于给定值yd(k)频繁升降的场…

isNotEmpty() 和 isNotBlank() 的区别,字符串判空, StringUtils工具包 StringUtil工具类

目录1.StringUtils 和 StringUtilStringUtils 的依赖&#xff1a;StringUtils 的用法&#xff1a;StringUtil 工具类2. isNotEmpty() 和 isNotBlank()1.StringUtils 和 StringUtil 注&#xff1a;StringUtils 和 StringUtil 的区别&#xff08;StringUtil为自定义工具类&#…

微信小程序——获取接口调用凭据access_token

问题背景 今天在搞一个微信小程序的时候&#xff0c;使用到了发布内容的问题&#xff0c;然后想使用微信请求接口&#xff0c;结果遇到了请求接口需要获取调用凭证access_token。 查看微信小程序开发文档 打开微信小程序开发文档后&#xff0c;打开服务端相关文档&#xff0…

电影《流浪地球2》观后感

趁着过年看了电影《流浪地球2》这部电影&#xff0c;同时也听说&#xff0c;今天好几部同期电影也不错&#xff0c;思考了一下&#xff0c;选择这部&#xff0c;记得以前有个笑话&#xff0c;说《流浪地球》成功开启了中国科幻的大门&#xff0c;而另一部电影成功将这部大门关起…