Linux线程同步(上)

news2024/12/21 11:20:20

在这里插入图片描述

文章目录

  • 1. 同步的概念
  • 2. 条件变量函数
    • 2.1 等待函数
    • 2.2 样例
  • 3. 生产者消费者模型
  • 4. 阻塞队列
    • 4.1 模拟阻塞队列的生产消费模型
    • 4.2 构造函数和析构函数
    • 4.3 生产接口和消费接口
    • 4.4 创建线程进行测试

1. 同步的概念

互斥可能会导致一个执行流长时间得不到某种资源。也叫饥饿问题。

在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步

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

那么同步可以解决饥饿问题,也可以让线程协同。我们要让线程同步就需要条件变量。

2. 条件变量函数

条件变量的目的是:让原本系统唤醒线程改成由程序员自己唤醒
在这里插入图片描述
条件变量的函数和锁的函数是类似的。如果是全局变量或者静态的可以使用宏来定义。如果是局部变量,可以用pthread_cond_init来初始化。

2.1 等待函数

等待条件:
在这里插入图片描述
条件变量要和互斥锁mutex一并使用。
唤醒等待:
在这里插入图片描述
第一个函数是在这个条件下唤醒一批线程,第二个是在这个条件下唤醒一个线程。

为什么 pthread_cond_wait 需要互斥量?
条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程。
条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据
这里条件的意思是:共享资源的状态,例如抢票里面的tickets是否大于0。条件变量的意思是:条件满足或不满足的时候,进行wait或signal的一种方式

2.2 样例

在这里插入图片描述
这里我们就开始定义一个条件变量,然后初始化。
在这里插入图片描述
三个线程,都会在条件变量下进行排队等待,当我们主线程按顺序去唤醒某个线程,那个线程就会执行打印。
在这里插入图片描述
每当我们输入n的时候就唤醒一个线程。
在这里插入图片描述
我们可以看到3个线程就按照一定的顺序来打印了。输入其它的就退出了,然后主线程就开始等待其它线程,但其它线程都在阻塞等待,所以进程就不动了。
在这里插入图片描述
我们在break之后,把所有的线程都给唤醒,然后终止线程。
在这里插入图片描述
我们可以看到还是不行。

我们可以这样设置:
在这里插入图片描述
在这里插入图片描述
如果我们输入的是n就全部唤醒线程,如果不是就把quit设置成true,然后break,在主线程中再次把全部线程唤醒。这样每个线程都会执行一次run打印,然后判断退出再打印一下end打印。

这样对不对呢?我们看一下运行结果:
在这里插入图片描述
我们看到只退出一个线程,其它线程没有退出。

这个和pthread_cond_wait函数有关,在4.3中进行了解释:当全部线程都被唤醒时,就会自动加锁,那么这几个线程都会去抢锁,但只有一个线程能抢到锁,当这个线程退出的时候也把锁带走了。所以其它线程就竞争不到锁了,就退出不了。

解决办法:
在这里插入图片描述
那么我们就可以这样修改:
在这里插入图片描述
我们手动加锁和解锁。

在这里插入图片描述
这样我们就能全部退出了。

还有一种方法:
在这里插入图片描述
我们让每个线程分离,它也可以退出。
在这里插入图片描述

那么我们也可以定义一个方法集,让不同线程执行不同函数:
在这里插入图片描述
在这里插入图片描述
加载到vector中,然后让线程去执行:
在这里插入图片描述
在这里插入图片描述

3. 生产者消费者模型

举个例子:
在这里插入图片描述
平时我们在买东西的时候,一般是去超市里购买,而不是直接去生产商里,如果我们去生产商买,还需要等它做好,而去超市就可以直接拿到。这样就提高了效率。另外,我们在买东西的时候,生产商可以不生产,我们不买东西的时候,生产商可以生产,或者我们一边买东西,生产商一边生产。这样就是一种解耦的关系。

在OS中,消费者就是消费线程,生产者就是生产线程,超市是个临界资源,相当于一个缓冲区,平衡了生产者和消费者的处理能力

1.那么消费者有多个,消费者之间是什么关系呢

2.生产者有多个,生产者之间是什么关系呢

这两个问题比较简单,是竞争关系,也就是互斥关系

3.那么消费者和生产者之间是什么关系呢
我们知道,如果我们要买个东西,超市没有,那么我们就需要等待生产者,如果没有人买某个东西,那么生产者就需要等消费者,它们是同步关系。那么在生产者给超市货时,消费者不能直接去生产者手中拿,而是等生产者将货放好到超市,消费者才能拿。这也体现了互斥关系。
所以既有互斥关系和同步关系

总结:
3种关系:生产者和生产者(互斥),消费者和消费者(互斥),生产者和消费者(同步和互斥)。
2种角色:生产者和消费者,由线程承担。
1个交易所:超市,内存中一种特定的数据结构

4. 阻塞队列

在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构。其与普通的队列区别在于:当队列为空时,从队列获取元素的操作将会被阻塞,直到队列中被放入了元素;当队列满时,往队列里存放元素的操作也会被阻塞,,直到有元素被从队列中取出
以上的操作都是基于不同的线程来说的,线程在对阻塞队列进程操作时会被阻塞。

4.1 模拟阻塞队列的生产消费模型

在makefie里面我们是可以定义变量的:
在这里插入图片描述
然后我们可以用这些变量来替换,格式为$(变量名)

下面我们就需要完成3个步骤:
1.定义一个阻塞队列。
2.创建两个线程,productor,consumer(生产者和消费者)。
3.让productor和consumer进行联系

在这里插入图片描述
在BlockQueue.hpp里面定义一个阻塞队列。

从上面的原理,我们知道要模拟一个阻塞队列的生产者消费模型,需要阻塞队列,阻塞队列的容量,互斥锁和条件变量。
在这里插入图片描述

4.2 构造函数和析构函数

在这里插入图片描述

4.3 生产接口和消费接口

生产线程和消费线程它们的工作分为3步:
1.为了保护阻塞队列,我们需要加锁。
2.生产者:判断阻塞队列是否为满,满的话不生产,生产线程休眠。不满的话就生产,并且唤醒消费者。
消费者:判断阻塞队列是否为空,空的话不消费,消费线程休眠。不空的话就消费,并且唤醒生产者。
3.解锁

在这里插入图片描述
首先,我们完成加锁和解锁的封装,这个是比较简单的。封装的意义是如果我们不用queue,可以方便修改。
在这里插入图片描述
在这里插入图片描述
这是第二步操作,判断阻塞队列满不满足,不满足就阻塞等待。
在这里插入图片描述
为什么这里等待的时候需要传mutex_呢
在阻塞线程的时候,会自动释放mutex_锁
如果生产者先加锁然后条件不满足,就会阻塞等待,如果不自动释放mutex_锁,就会带着锁等待,那么消费者就不能加锁去消费了。
在唤醒的时候,它也是在这个等待函数后被唤醒,那么在访问临界区的时候是不是就没有锁呢
当阻塞结束,返回的时候,pthread_cond_wait,会自动帮你重新获得mutex_,然后才返回
在这里插入图片描述
在这里插入图片描述

到这里就是条件满足,消费后,把消费的数据返回。
在这里插入图片描述
在这里插入图片描述
在生产或者消费之后,我们需要唤醒对方。
在这里插入图片描述
这里还存在一些问题:
1.pthread_cond_wait函数调用失败了呢?wait失败,没有阻塞成功,继续往下执行。
2.可能由于某种原因进行的伪唤醒,但是现在条件并没有满足

这样线程可能在条件满足的情况下继续往下执行。
在这里插入图片描述
当线程醒来的时候,我们再次去判断条件满不满足,这样代码的健壮性更强。

4.4 创建线程进行测试

现在我们需要创建两个线程productor,consumer让它们进行联系:
在这里插入图片描述
在这里插入图片描述
我们在这里定义一个随机数种子,异或pid是增加随机性。
在这里插入图片描述
我们让生产者2秒生产一个,消费者一直消费,这样消费者就会按照生产者的节奏来。
在这里插入图片描述
在这里插入图片描述
这里我们再让生产者一次生产多个,然后消费者每隔2秒消费一个。
在这里插入图片描述

既然可以使用int类型的数据,我们也可以使用自己封装的类型,包括任务
在这里插入图片描述
这个任务比较简单,是一个计算加减乘除取模的任务。
在这里插入图片描述
生产者给阻塞队列放任务,消费者去完成任务。
在这里插入图片描述
生产者消费者模型优点是支持并发的,但是上面只体现了互斥,我们该如何理解呢
那么我们知道:制作任务和处理任务是需要花费时间的,那么就有可能当生产者在生产时,消费者就在消费了。生产者和消费者在阻塞队列中确实是互斥的,因为有锁,但是生产者在生产的时候,消费者在消费的时候,这个是同步的。

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

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

相关文章

健身房小程序怎么做?

如果把预约小程序用好了,会给你的场馆经营带来很多意想不到的好处,解决用户线上约客的问题,顶多只发挥了 20% 的作用,那另外 80% 的用法是什么呢? 高效推荐名片服务行业做的是口碑,用户靠的是转介绍&#x…

SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础》提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/signalr/overview/getting-started…

超大模型如何实现3D WEB轻量化渲染?

Hoops Communicator是Tech Soft 3D旗下的主流产品之一,具有强大的、专用的高性能图形内核,专注于基于Web的高级3D工程应用程序。其由HOOPS Server和HOOPS Web Viewer两大部分组成,提供了HOOPS中的HOOPS Convertrer、Data Authoring的模型转换…

电脑提示msvcr120.dll丢失的解决方法win10,总共有三种,那个更方便

电脑修复经验分享,dll动态链接库文件丢失修复教程,DLL 文件,即动态链接库,也有人称作应用程序拓展。一种可执行文件,允许程序共享执行特殊任务所需的代码和其他资源。msvcr120.dll也是属于dll文件之一,在Wi…

python 面向对象 对象

类 构造函数 # 创建类 class Student:name None # 成员属性age None # 成员属性def say(self): # 成员方法print(self.name)# 构造函数def __init__(self,name,age):self.name nameself.age age#创建类对象 my_student Student() # 对象的属性 赋值 my_student.name …

Mysql数据库——用户管理与授权

Mysql数据库——用户管理与授权 一、登录用户的管理1.新建用户2.查看用户信息3.重命名用户4.删除用户5.修改当前登录用户密码6.修改其他用户密码7.忘记 root 密码的解决办法 二、数据库用户授权…

【Docker】Docker中Linux 容器、网络虚拟化与虚拟局域网的技术特点详细讲解

前言 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 📕作者简介:热…

Stream流学习前置知识之匿名内部类

目录 匿名内部类 概念 语法体 案例演示 匿名内部类 概念 没有名字的内部类 用于在程序中创建一个只使用一次的临时类 使用 new 关键字来创建一个对象,重写该类的方法或实现该类的接口 语法体 new 父类构造器或接口() {// 匿名内部类的定义 } 案例演示 T…

【深度学习】基于Qt的人脸识别系统,门禁人脸识别系统,Python人脸识别流程,树莓派

文章目录 人脸识别过程人脸检测人脸对齐人脸特征提取特征距离比对人脸识别系统 人脸识别过程 在深度学习领域做人脸识别的识别准确率已经高到超出人类识别,但综合考虑模型复杂度(推理速度)和模型的识别效果,这个地方还是有做一些…

网络安全大厂面试题合集+面试题文档

以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题&#xf…

阿里巴巴开源Chat2DB v1.0.11 初体验

阿里巴巴开源Chat2DB v1.0.11 初体验 前言什么是Chat2DB下载安装安装配置Chat2DB初体验配置数据源准备测试数据认识几个功能菜单开始测试自然语言转SQLSQL解释SQL优化 使用总结后续功能结语 前言 作为一名阿里巴巴开源项目的拥护者,从Chat2DB开源至今都有关注这个开…

计算机视觉重磅会议VAlSE2023召开,合合信息分享智能文档处理技术前沿进展

近期,2023年度视觉与学习青年学者研讨会 (Vision And Learning SEminar, VALSE) 圆满落幕。会议由中国人工智能学会、中国图象图形学学会主办,江南大学和无锡国家高新技术产业开发区管理委员会承办。超五千名专家学者、知名高校师生以及来自OPPO、华为、…

docker 容器的网络类型

目录 vmware的三种网卡模式(网络模式) docker里的四种网络类型 参考资料:Docker四种网络模式 - 简书 (jianshu.com) 1、桥接模式(默认情况) 2、host模式 3、none模式 4、container模式 创建桥接模式网卡 网卡…

TensorFlow Core—基本分类:对服装图像进行分类

现在人工智能很火的,看到了这篇文章,给自己普及一下基础知识,也分享给大家,希望对大家有用。 本指南将训练一个神经网络模型,对运动鞋和衬衫等服装图像进行分类。即使您不理解所有细节也没关系;这只是对完…

「FPGA」基本时序电路元件——锁存器和触发器

「FPGA」基本时序电路元件——锁存器和触发器 文章目录 「FPGA」基本时序电路元件——锁存器和触发器1. 最简单的双稳态元件2. SR锁存器3. D锁存器(data latch)4. D触发器5. 寄存器(register) FPGA是一种数字电路实现的方式&#…

算法设计与分析知识点整理

文章目录 前言一、算法的基本概念1.算法的基本特征2.算法设计需要满足的目标3.算法和程序的区别 二、时间复杂度计算1.大O表示法2.最坏和平均情况3.根据递归方程求解时间复杂度3.1 根据递归树求解3.2 根据主方法求解 三、六大算法1.分治法1.1 算法思路1.2 适用范围1.3 基本步骤…

【MySql】聚合函数group byOJ题目

文章目录 聚合函数分组group by使用OJ题目描述描述 本篇主要介绍mysql的聚合函数和group by的使用,最后是OJ题目的练习。 聚合函数 MySQL中的聚合函数用于对数据进行计算和统计,常见的聚合函数包括下面列举出来的聚合函数: 函数 说明…

python开发构建深度学习分类模型,探索AI在地震事件分类中的应用于可解释性分析

最近看到了一篇蛮有意思的论文,如下: 将深度学习开发应用到了地震事件分析分类领域中去了,感觉挺有意思,就想着也来自己体验下看看,这里的数据集是网上找到的一个地震波应该是仿真实验的数据集,我们先来看下…

Pytest教程__Hook函数pytest_addoption(parser):定义自己的命令行参数(14-1)

考虑场景: 我们的自动化用例需要支持在不同测试环境运行,有时候在dev环境运行,有时候在test环境运行;有时候需要根据某个参数不同的参数值,执行不同的业务逻辑; 上面的场景我们都可以通过“在命令行中输入…

浏览器之BFC

浏览器之BFC 什么是BFCBFC的特性特性1:BFC会阻止垂直外边距折叠①相邻兄弟元素margin重叠问题②父子元素margin重叠问题 特性2:BFC不会重叠浮动元素BFC可以包含浮动----清除浮动 什么是BFC Block formatting context直译为"块级格式化上下文Block …