Linux--线程互斥与同步--0112 13

news2024/11/29 20:48:38

线程互斥

1.背景概念

临界资源:多线程执行流共享的资源就叫做临界资源。

临界区:每个线程内部,访问临界资源的代码就叫做临界区。

互斥:任何时刻,互斥保证有且只有一个执行流进入临界区 ,对临界资源起保护作用。

原子性:可以被调度机制打断,但是操作只有两种情况,要么做完了,要么没做。

2. 互斥量(加锁)

//定义全局的一把锁 并初始化

pthread_mutex_t mtx=PTHREAD_MUTEX_INITIALIZER

//在临界区上锁

pthread_mutex_lock(&mtx);

//临界区结束解锁

pthread_mutex_unlock(&mtx);

 注意:

加锁的范围一定要尽可能小。

全局变量的锁不需要销毁。


定义局部的一把锁

//初始化

pthread_mutex_init(&mtx,nullptr);

//上锁 和解锁相同

//释放

pthread_mutex_destroy(&mtx);

 2.1 互斥量的相关问题

  • 加锁之后,线程在临界区是否还能进行程序替换?

可以切换,但是是在自己持有锁的情况下进行的程序替换。其他线程如果要执行临界区的代码,依然需要申请锁,持有锁的线程不执行完毕解锁,其他线程无法进入临界区。这就保证了临界区中数据的一致性。

  • 线程访问临界区一定需要先申请锁。

如果一个线程不申请锁就去访问临界资源,这就是一种错误的编码方式。

 2.2 互斥量实现的原理

当线程A进行movb 时 al中放入了0,假设此时A线程的时间片到了,A就会拿着寄存器中A的上下文数据(0)结束调度。此时B进程进来,依然在进行movb时,将al放入0,然后继续执行第二步,xchgb,将mtx和al的值进行交换。此时al是1 mtx是0 。

进行判断,大于0,进入if语句。假设在return 0 这步,B线程的时间片到了,B线程就带着执行到的步数,以及自己的上下文数据走了。

A线程进入CPU,继续上次未执行的地方开始运行。xchgb 交换了0和 0 。

进行判断,不符合走入了else语句,进行阻塞等待。再被切换回来时,执行goto lock 语句,如果B线程执行完毕,将1给mutex,那么A线程在交换时,al就可以成为1,进而成功申请锁,不然就是上述进行重复。

 3. 死锁

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

3.1 造成死锁的原因

线程在访问临界区的时候,可能不止需要申请一把锁。假设有两个线程A和B,线程A需要先申请锁1,再申请锁2,线程B需要先申请锁2,再申请锁1。如果二者同时拥有自己需要申请的第一把锁,那么这个进程进入死锁。

死锁:持有锁的线程,在持有自身锁的情况下,向对方申请对方的锁,进而导致代码无法推进。

 3.2 死锁的四个必要条件

互斥条件:一个资源每次只能被一个执行流使用。

请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放。

不剥夺条件:一个执行流获得的资源,在未使用完之前,不能强行剥夺。

循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系。

3.3 避免死锁

  • 破坏上述必要条件。
  • 加锁顺序保持一致。
  • 临界区外及时释放锁。
  • 资源一次性分配。(一次性访问临界资源,不要访问一次加一把锁)

 4. 可重入与线程安全

4.1 联系

  • 如果函数是可重入的,那该函数一定是线程安全的。
  • 如果函数是不可重入的,那该函数有可能引发线程安全问题。
  • 如果一个函数中有全局变量,那这个函数既不是可重入函数,也不是线程安全的。

4.2 区别

  • 可重入函数是线程安全函数中的一种。
  • 线程安全不一定是可重入的,而可重入的一定是线程安全的。
  • 可重入函数加锁是线程安全的,但在锁未释放之前是不可重入的。

线程同步

按照一定顺序,进行临界资源的访问,称为线程同步

因为时序问题,而导致程序异常,称为竞态条件

当我们申请临界资源时,要先检测临界资源是否存在,但是做检测也是对临界资源的访问。这也处在加锁和解锁之间。如果使用这种方式,注定了我们一定会频繁的申请和释放锁。

所以我们需要其他的方式让线程检测到资源不就位的情况,在这种情况下,不再让线程频繁检测,等待。当资源就绪时,再通知对应的线程,让他们来进行资源申请和访问。

5.条件变量函数

5.1.1 初始化

  •  如果是全局的或者静态的
pthread_cond_t cond =PTHREAD_COND_INITIALIZER;
  •  局部的
//先定义一个
pthread_cond_t restrict;
//初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict
attr);

 局部的需要销毁

int pthread_cond_destroy(pthread_cond_t* cond);

参数介绍

cond : 要初始化的条件变量

attr :NULL


5.1.2 等待条件满足

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t* restrict cond,pthread_mutex_t* restrict mutex);

 参数介绍

 cond:要在这个条件变量上等待
mutex:互斥量,后面详细解释


 5.1.3 唤醒等待

int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);

pthread_cond_broadcast  把所有线程全部唤醒

pthread_cond_signal 唤醒对应的那个线程


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

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

相关文章

36岁北邮硕士,四段大厂经历,当初为了涨薪频繁跳槽,被裁后投遍所有公司,基本都不回复!...

今天给大家分享一位36岁北邮硕士的职场经历&#xff1a;2013年北邮硕士毕业后&#xff0c;分别在乐视、字节、阿里、小米待过&#xff0c;2022年被小米裁员&#xff0c;几乎投遍了boss上所有公司&#xff0c;基本都是已读不回。只有一个小公司的hr看了简历后回了一句“加油”。…

绕过某博客查看文章验证码,关注公众号得验证码

之前也写过一篇&#xff0c;当时使用Burpsuite抓包&#xff0c;改包&#xff0c;有点杀鸡用牛刀了。 虽然我挺支持为知识那啥的&#xff0c;但是吧要我去关注公众号太麻烦了 绕过查看文章需要验证码 其实就是改一个返回的字段&#xff0c;既然后端也是改&#xff0c;那我前端…

Google Earth Engine基础使用方法(一)

Google Earth Engine 1、注册账号1.1、设置谷歌账号辅助邮箱1.2、进入Google Earth Engine(如果第一次注册失败怎么办)1.3、进入Google Earth Engine Editor2、Editor主界面2.1、上传自己的矢量数据2.2、分享代码给别人2.3、保存代码2.4、几个有效快捷键2.5、搜索框有什么用3、…

SAP S/4 FAGLGVTR错误解决

本次年结支持过程中&#xff0c;一个客户的年结操作出现问题&#xff0c;问题的解决还颇费周折&#xff0c;稍稍记录一下。客户的SAP 版本是 S/4, 通过 FAA_CMP 事务码切换固定资产年度的时候&#xff0c;提示上一已关闭的会计年度与当前会计年度相同。 这个消息的意思是FI 的会…

【自学Python】Python字符串出现次数

Python字符串出现次数 Python字符串出现次数教程 在开发过程中&#xff0c;很多时候我们有统计单个字符或者 字符串 在另一个字符串中出现次数的需求&#xff0c;在 Python 中&#xff0c;统计字符串出现次数我们使用 count() 函数。 Python count()函数详解 语法 S.count…

Python实战项目1——自动获取小说工具

&#x1f935;‍♂️ 个人主页老虎也淘气 个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f44d;&#x1f3fb; 收藏…

【C++】二叉树进阶OJ题

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;根据二叉…

前端开发:Webpack的使用总结

前言 在前端开发过程中&#xff0c;尤其是现在前端框架的频繁使用的当下&#xff0c;作为前端开发者想必对于Webpack并不陌生&#xff0c;尤其是在使用Vue框架做前端开发的时候&#xff0c;打包时候必用Webpack。还有就是在前端求职面试的时候&#xff0c;Webpack相关的知识点…

mysql新建分区设置阈值(less than)引发的问题

mysql新建分表后&#xff0c;入库之前分表区间的数据&#xff0c;但是再分表中查询不到对应数据。 文章目录问题背景问题解析新建分区sql查看分区查询数据查询数据所在分区修改方案总结LESS THAN相关sql查询分区删除分区先建分区问题背景 初始化表的时候&#xff0c;先建的日期…

(二)Jenkins全局工具配置

目录 1、插件管理 2、Gitee安装 2.1、插件安装 2.2、查看Gitee状态 2.3、配置Gitee 2.4、获取私人令牌 2.5、测试连接 3、全局配置jdk、ant、maven 3.1、jdk配置 3.2、ant配置 3.3、maven配置 4、插件镜像下载地址配置 (一)Jenkins部署、基础配置介绍在windows下安…

事务(transaction)

事务&#xff08;重点 五颗星 ***** 必须理解 必须掌握&#xff09; 1、什么是事务&#xff1a; 一个事务其实就是一个完整的业务逻辑。 假设转账&#xff0c;从A账户向B账户转账10000.将A账户的钱减去10000&#xff08;update语句&#xff09;&#xff0c;将B账 户的钱增加100…

【手写 Vue2.x 源码】第二十六篇 - 数组依赖收集的实现

一&#xff0c;前言 上篇&#xff0c;主要介绍了数组依赖收集的原理 本篇&#xff0c;数组依赖收集的实现 二&#xff0c;对象依赖收集的总结 {}.dep > watcher 目前&#xff0c;“对象本身”和“对象中的每一个属性”都拥有一个 dep 属性&#xff0c;用于做依赖收集 此…

Leetcode:669. 修剪二叉搜索树(C++)

目录 问题描述&#xff1a; 实现代码与解析&#xff1a; 递归&#xff1a; 原理思路&#xff1a; 后序递归&#xff1a; 原理思路&#xff1a; 迭代&#xff1a; 原理思路&#xff1a; 问题描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界…

#9文献学习--基于元强化学习的边缘计算快速自适应任务卸载

文献&#xff1a;Fast Adaptive Task Offloading in Edge Computing based on Meta Reinforcement Learning 基于深度强化学习DRL的方法&#xff0c;样本效率很低&#xff0c;需要充分的再培训来学习新环境的更新策略&#xff0c;对新环境的适应性很弱。 基于元强化学习的任务…

【数据结构与算法】第十八篇:递归,尾递归,尾调用

知识概览一、递归的引入&#xff08;递归现象&#xff09;二、递归的调用过程与实例分析三、递归的基本思想小tip:链表递归的具体实例四、递归的一般使用条件五、实例分析&#xff1a;斐波那契数列1.原理剖析2.fib优化1 – 记忆化3.fib优化24.fib优化3六、实例分析&#xff1a;…

mac下ssh连接docker使用centos

配置ssh连接docker本机信息 Apple M2/ macOS Ventura 13.1完整实现如下&#xff1a;使用docker下载centos镜像docker pull centos:centos7 # centos7 指定安装版本查看本地镜像# 使用以下命令查看是否已安装了centos7➜ ~ docker images REPOSITORY TAG IMAGE ID …

c++通讯录管理系统

结构体1&#xff0c;知识点&#xff08;结构体&#xff09;&#xff0c;存放人员详情&#xff0c;名字&#xff0c;性别&#xff0c;年龄等 struct person { string m_name; int m_sex; int m_age; string m_phone; string m_addr; };结构体2&#xff0c;知识点 &#xff08;结…

狗厂的N+1+2毕业,我觉得还是挺良心的

最近又跟朋友打听到了新鲜事&#xff0c;年底的新鲜事&#xff0c;什么209万&#xff0c;就是听个乐子&#xff0c;离我太远&#xff0c;什么HR和技术人员产生矛盾&#xff0c;一巴掌眼镜都打飞了&#xff0c;好乱套&#xff0c;今天我跟朋友打听了一些不太乱套的 一、鹅肠 1.…

Quartz认知篇 - 初识分布式任务调度Quartz

定时任务的使用场景 在遇到如下几种场景可以考虑使用定时任务来解决&#xff1a; 某个时刻或者时间间隔执行任务 批量数据进行处理 对两个动作进行解耦 Quartz 介绍 Quartz 是一个特性丰富的、开源的任务调度库&#xff0c;几乎可以嵌入所有的 Java 程序&#xff0c;包括很…

基于二叉树的改进SPIHT算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…