【多线程】线程同步--条件变量的原理及其使用

文章目录

  • 前言
  • 线程同步的基本概念
    • 条件变量
      • 定义条件变量
      • 初始化条件变量
      • 销毁条件变量
      • 等待条件(重要)
      • 唤醒等待
      • 简单运用
      • 常见使用条件变量的格式

前言

线程同步意味着在多线程并发执行中,协调线程之间的执行顺序,以确保共享资源被正确访问和修改。线程同步的维护本质就是在安排线程之间的执行顺序。那么在linux中是如何维护线程同步的呢?本篇文章将围绕这个为题展开叙述。

线程同步的基本概念

下面介绍一些有关线程同步的基本概念。

条件变量

当一个线程互斥的访问某个变量,即访问临界资源时给临界区上互斥锁,这个时候其它线程只能等待。那什么时候其它线程可以继续申请临界资源呢?我们希望当一个线程使用完临界资源后,正在等待的线程能够知道这一事件的发生从而重新申请资源,而不是一直重复申请这个动作

就像一个闹钟,当闹钟响了之后我们就知道该起床了,而不是睡一下又看下时间。

条件变量提供一种线程通信的方法,使得一个线程可以等待另一个线程满足某种条件后再继续执行。具体的,我们将这种通知一个线程继续执行的动作称为唤醒

于是,借助条件变量,我们就能实现协调线程之间访问临时资源的顺序性。

同时线程库给我们提供了一些接口用来操作条件变量,下面介绍一些常见的关于条件变量的操作。(头文件都是pthread.h

定义条件变量

初始化条件变量

  1. 动态初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr); 
  • cond :要初始化的条件变量
  • attr:条件变量的属性,通常是NULL
  1. 静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

销毁条件变量

int pthread_cond_destroy(pthread_cond_t *cond);

销毁某个条件变量,成功返回0,失败返回错误代码
在这里插入图片描述

等待条件(重要)

如果当前线程没有申请到临界资源,该线程可以选择等待。

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

在调用该函数时,互斥锁mutex必须被锁住,并等待唤醒。唤醒之后线程重新锁住互斥锁并继续执行。值得注意的是,pthread_cond_wait函数首先会解锁与之关联的互斥锁mutex,这也是为什么使用该函数时mutex必须是被锁住的。然后调用该函数的线程进入阻塞状态,直到被唤醒。最后,条件变量被通知之后,pthread_cond_wait重新锁定互斥锁mutex
对于该函数提出以下问题:

  • 为什么要在pthread_cond_wait中传入互斥锁
    • 在调用 pthread_cond_wait 时,互斥锁是已经锁住的,确保没有其他线程可以修改共享资源。
    • pthread_cond_wait 在进入等待状态之前会自动释放互斥锁,使得其他线程可以修改条件。
    • 当线程被唤醒后,pthread_cond_wait 会重新获得互斥锁,然后再继续执行,因为此时还在临界区,还会访问临界资源。

唤醒等待

  1. 唤醒某个线程
int pthread_cond_signal(pthread_cond_t *cond);

唤醒一个等待在条件变量 cond 上的线程。如果有多个线程在等待条件变量,具体唤醒哪一个线程是不确定的。
成功返回0,失败则返回错误码

  1. 唤醒所有正在等待该条件变量的线程
int pthread_cond_broadcast(pthread_cond_t *cond);

唤醒所有等待在条件变量 cond 上的线程。同样成功返回0,失败则返回错误码。

简单运用

下面我们使用条件变量和互斥锁来设计一个简单的代码样例

#include <iostream>
#include <unistd.h>
#include <pthread.h>using namespace std;pthread_cond_t cond;
pthread_mutex_t mutex;void *r1(void *arg) // 等待函数,执行该函数的线程一直处于while (true)
{pthread_cond_wait(&cond, &mutex);cout << "被唤醒" << endl;return arg;
}void *r2(void *arg) // 唤醒函数,执行该函数的线程一直尝试唤醒某个等待的线程
{while (true){pthread_cond_signal(&cond);cout << "唤醒某个线程" << endl;sleep(1);}
}int main()
{pthread_t t1, t2; // 定义两个线程pthread_cond_init(&cond, NULL);   // 初始化条件变量pthread_mutex_init(&mutex, NULL); // 初始化互斥锁pthread_create(&t1, NULL, r1, NULL); // 创建线程并分配执行函数pthread_create(&t1, NULL, r2, NULL);pthread_join(t1, NULL); // 等待线程退出pthread_join(t2, NULL);pthread_mutex_destroy(&mutex); // 销毁互斥锁和条件变量pthread_cond_destroy(&cond);return 0;
}

在这里插入图片描述

常见使用条件变量的格式

  • 等待条件代码:
pthread_mutex_lock(&mutex); while (条件为假) //不满足条件陷入等待,在循环中等待是为了防止伪唤醒pthread_cond_wait(cond, mutex); 
// ...
// 访问临界资源//...pthread_mutex_unlock(&mutex); 
  • 给条件发送信号,即可以唤醒等待条件中的线程
pthread_mutex_lock(&mutex); 设置条件为真 pthread_cond_signal(cond); //唤醒某个线程pthread_mutex_unlock(&mutex); 

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

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

相关文章

hive架构详解:HQL案例解析(第15天)

系列文章目录 一、Hive基础架构&#xff08;重点&#xff09; 二、Hive数据库,表操作&#xff08;重点&#xff09; 三、Hadoop架构详解(hdfs)&#xff08;补充&#xff09; 四、Hive环境准备&#xff08;操作&#xff09;(补充) 文章目录 系列文章目录前言一、Hive基础架构1、…

4. 小迪安全v2023笔记 javaEE应用

4. 小迪安全v2023笔记 javaEE应用 ​ 大体上跟随小迪安全的课程&#xff0c;本意是记录自己的学习历程&#xff0c;不能说是完全原创吧&#xff0c;大家可以关注一下小迪安全。 若有冒犯&#xff0c;麻烦私信移除。 默认有java基础。 文章目录 4. 小迪安全v2023笔记 javaEE应…

linux下安装cutecom串口助手;centos安装cutecom串口助手;rpm安装包安装cutecom串口助手

在支持apt-get的系统下安装 在终端命令行中输入&#xff1a; sudo apt-get install cutecom 安装好后输入 sudo cutecom 就可以了 关于如何使用&#xff0c;可以看这个https://www.cnblogs.com/xingboy/p/14388610.html 如果你的电脑不支持apt-get。 那我们就通过安装包…

‘wget‘ 不是内部或外部命令,也不是可运行的程序

在Windows环境下创建了虚拟环境并安装了wget包&#xff0c;但在使用该命令的时候仍然报错&#xff0c;‘wget’ 不是内部或外部命令,也不是可运行的程序 解决方案&#xff1a; 去官网下载对应位数的.exe文件&#xff0c;将其放在C:\Windows\System32目录下即可, 别下错版本&a…

宝塔面板部署Flask项目教程(最新版)

本教程适用于最新版的宝塔&#xff01;&#xff01;&#xff01; 本教程适用于最新版的宝塔&#xff01;&#xff01;&#xff01; 本教程适用于最新版的宝塔&#xff01;&#xff01;&#xff01; 1 准备 1.1 依赖文件 在你的项目根目录下生成一个依赖文件&#xff0c;执行…

美业收银系统怎么选?哪些功能实用?美业门店管理系统|拓客系统

选择美业会员系统时&#xff0c;你可以考虑以下几个方面的功能来确定哪些对你最实用&#xff1a; 1.会员管理&#xff1a; 系统应该能够轻松管理会员资料、积分、消费记录等信息&#xff0c;以便更好地了解客户需求并提供个性化服务。 2.促销与营销工具&#xff1a; 包括发…

3D云渲染工具对决:Maya与Blender的性能和功能深度比较

3D建模和动画制作已成为数字领域不可或缺的一环&#xff0c;无论是在影视特效的震撼场面&#xff0c;还是在游戏角色的生动表现&#xff0c;3D技术都扮演着至关重要的角色。而在这一领域&#xff0c;Maya和Blender这两款软件&#xff0c;以其强大的功能和广泛的应用&#xff0c…

【JavaEE】进程

目录 一.冯诺依曼体系结构 二.CPU的核心概念 核心数 频率&#xff08;Clock Speed 或时钟频率&#xff09; 如何选择合适的CPU 三.指令的执行 1.什么是指令 1.取指令 2.解析指令 3.执行指令 4.访问内存&#xff08;Memory&#xff09;: 5.写回结果&#xff08;Write…

视频解码故障案例两则

案例1 绿边 故障分析&#xff1a; 这个能明显看到视频上方出现绿色半透明边带。这说明Y数据正常。UV数据不正常。 它显然与视频帧的垂直分辨率设置有关。 UV数据和Y数据是连续放置的&#xff0c;如果上方出现彩色数据失调&#xff0c;说明这部分数据实际仍然是Y数据。也就是…

JAVASE进阶day08(Map双列集合)

HashMap 1.HashMap基本使用 package com.lu.day08.map;import java.util.HashMap; import java.util.Map; import java.util.Set;public class MapDome {public static void main(String[] args) {HashMap<String , String> map new HashMap<>();//添加后者修改-…

电脑32位和62位是什么意思

在现代计算机世界中&#xff0c;32位和64位是两个常见的术语&#xff0c;但许多用户可能不太清楚它们的确切含义以及它们之间的区别。本文将详细介绍32位和64位计算机的基本概念、如何查看您的计算机是32位还是64位&#xff0c;以及它们对用户的实际影响。 32位与64位的基本概…

【高中数学/指数函数】比较a=0.6^0.9 b=0.6^1.5 c=1.5^0.6的大小

【问题】 比较a0.6^0.9 b0.6^1.5 c1.5^0.6的大小 【解答】 指数函数y0.6^x是减函数&#xff0c;因为0.9<1.5,所以0.6^0.9>0.6^1.5,即a>b; 指数函数y1.5^x是增函数&#xff0c;1.5^0.6>1.5^01>0.6^0.9,即c>a; 综上&#xff0c;得出c>a>b的结论。 …

【运维】docker批量删除临时镜像(两种方式)

docker批量删除Tag<none>的临时镜像 在开发的时候&#xff0c;需要经常发布开发包&#xff0c;在使用docker build构建镜像的时候&#xff0c;同一个版本经常会使用相同tag&#xff0c;频繁打包一段时间后&#xff0c;本地会出现很多Tag<none>的临时镜像&#xff…

Xinstall揭秘:APP推广数据背后的真相,让你的营销更精准!

在这个移动互联网时代&#xff0c;APP如同雨后春笋般涌现&#xff0c;但如何在这片红海中脱颖而出&#xff0c;成为每一个开发者与运营者面临的共同难题。其中&#xff0c;APP推广统计作为衡量营销效果、优化推广策略的关键环节&#xff0c;更是不可忽视的一环。今天&#xff0…

你知道滚筒式高速视觉检测机外观怎么“看”出产品质量吗?

点火线圈胶套是一种用于保护点火线圈绝缘部分的胶质套管。这种胶套通常由高温耐磨的橡胶或硅胶材料制成&#xff0c;具有良好的绝缘性能和耐高温性能。点火线圈胶套的作用是防止点火线圈与外部环境接触&#xff0c;防止受潮、灰尘或化学物质的侵蚀&#xff0c;同时起到绝缘和保…

python怎么调用cmd命令

关于python调用cmd命令&#xff1a; 1、python的OS模块 OS模块调用CMD命令有两种方式&#xff1a;os.popen()、os.system()都是用当前进程来调用。 OS.system是无法获取返回值的。当运行结束后接着往下面执行程序。用法如&#xff1a;OS.system("ipconfig"). OS.…

随身WiFi市场乱象横生,随身WiFi测评最好的格行随身WiFi如何引领变革?

在当今随身WiFi市场乱象频发、内卷严重的背景下&#xff0c;消费者对于产品的性能与商家是否会后台割韭菜依旧存疑&#xff0c;尤其是“随身WiFi到底卡不卡&#xff1f;”的问题&#xff0c;成为了广大消费者关注的重点。然而&#xff0c;在众多品牌中&#xff0c;格行随身WiFi…

【音频特征提取】傅里叶变换算法源码学习记录

目录 背景快速理解FFT&#xff08;快速傅里叶变换&#xff09;IFFT&#xff08;逆傅里叶变换&#xff09;STFT&#xff08;短时傅里叶变换&#xff09; 代码实现FFT源代码IFFT源代码FFT、IFFT自己实验STFT源代码STFT自己实验 总结 背景 最近用到了相关操作提取音频信号特征&am…

标签印刷检测,如何做到百分百准确?

印刷标签是一种用于标识、识别或包装产品的平面印刷制品。这些标签通常在纸张、塑料膜、金属箔等材料上印刷产品信息、条形码、图像或公司标识&#xff0c;以便于产品识别和管理。印刷标签有各种形状、尺寸和材质&#xff0c;可以根据具体需求进行定制设计。常见的印刷标签包括…

FlutterFlame游戏实践#15 | 生命游戏 - 演绎启动

theme: cyanosis 本文为稀土掘金技术社区首发签约文章&#xff0c;30天内禁止转载&#xff0c;30天后未获授权禁止转载&#xff0c;侵权必究&#xff01; Flutter\&Flame 游戏开发系列前言: 该系列是 [张风捷特烈] 的 Flame 游戏开发教程。Flutter 作为 全平台 的 原生级 渲…