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

news2024/11/14 6:41:01

文章目录

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

前言

线程同步意味着在多线程并发执行中,协调线程之间的执行顺序,以确保共享资源被正确访问和修改。线程同步的维护本质就是在安排线程之间的执行顺序。那么在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.coloradmin.cn/o/1914997.html

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

相关文章

(一)、python程序--模拟电脑鼠走迷宫

一、绪论 1、简介 电脑鼠走迷宫是一种比赛&#xff0c;制作实物电脑鼠小车在迷宫找目标点&#xff0c;用时最短者获胜。考验参赛选手软硬件结合的能力。 2、走迷宫模拟软件中已实现功能 1、点击迷宫墙壁可编辑迷宫&#xff0c;并且可保存和加载迷宫形状文件&#xff1b; 2、…

即时通讯平台项目测试(主页面)

http://8.130.98.211:8080/login.html项目访问地址&#xff1a;即时通讯平台http://8.130.98.211:8080/login.html 本篇文章进行项目主页面的测试。 在测试前需要先对待测内容进行分类&#xff0c;按照功能进行分类可以分为&#xff1a;个人信息设置、发送/接收消息、添加好友…

YOLO V8-Pose 【批量图片推理】 推理详解及部署实现

前言 在实际处理过程中&#xff0c;我们使用YOLO V8进行推理时&#xff0c;通常会针对一张图片进行推理。如果需要对多张图片进行推理&#xff0c;则可以通过一个循环来实现对图片逐张进行推理。 单张图片推理时&#xff0c;需要注意图片的尺寸必须是32的倍数&#xff0c;否则…

游戏AI的创造思路-技术基础-情感计算(1)

游戏中的AI也是可以和你打情感牌的哦&#xff0c;不要以为NPC是没有感情的&#xff0c;不过&#xff0c;不要和NPC打过多的情感牌&#xff0c;你会深陷其中无法自拔的~~~~~~ 目录 1. 情感计算算法定义 2. 发展历史 3. 公式和函数 3.1. 特征提取阶段 TF-IDF&#xff08;词频…

算法学习笔记(8.1)-动态规划入门

目录 问题特性&#xff1a; 最优子结构&#xff1a; 代码示例&#xff1a;&#xff08;动态规划最优子结构&#xff09; 上述最小代价爬楼梯的运行过程&#xff1a; 代码示例&#xff1a; 无后效性&#xff1a; 解析&#xff1a; 具体过程图示如下&#xff1a; 具体的…

算法的复杂度

文章目录 一、算法的效率1、复杂度的概念2、复杂度的重要性 二、时间复杂度三、空间复杂度四、大O的渐进表示发五、计算复杂度案例1、计算Func1函数的复杂度2、计算Fun2的时间复杂度3、计算Func3的时间复杂度4、计算Func4的时间复杂度5、计算strchr的时间复杂度6、计算Func5的时…

解决Invalid or unsupported by client SCRAM mechanisms(dbeaver)

在用工具&#xff08;dbeaver&#xff09;链接Opengauss数据库的时候&#xff0c;报出标题的错误。原因为驱动不正确。 驱动下载地址&#xff1a;https://opengauss.org/zh/download/ 下载完的包 &#xff0c;解压后&#xff0c;里面应该有两个jar 包,使用postgresql.jar dbe…

MT3056 交换序列

思路&#xff1a; 与题目 MT3055 交换排列 类似 代码&#xff1a; #include <bits/stdc.h> using namespace std; const int N 1e4 10; int n, fa[N], b[N], d[N]; void init(int n) {for (int i 1; i < n; i)fa[i] i; } int find(int x) {return x fa[x] ?…

WebRTC批量发送消息API接口的特性有哪些?

WebRTC批量发送消息api接口怎么样&#xff1f;接口性能怎么用&#xff1f; WebRTC技术允许浏览器和移动应用进行实时通信。通过WebRTC&#xff0c;开发者可以构建视频、语音、数据共享等应用。AokSend将重点探讨WebRTC批量发送消息API接口的特性。 WebRTC批量发送消息API接口…

Qt/QML学习-PathView

QML学习 PathView例程视频讲解代码 main.qml import QtQuick 2.15 import QtQuick.Window 2.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")color: "black"PathView {id: pathViewanchors.fill: parentmodel: ListModel {List…

[Spring] SpringBoot基本配置与快速上手

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

AJAX-个人版2.0

AJAX&#xff08;Asynchronous Javascript And Xml&#xff09; 传统请求及缺点 传统的请求都有哪些&#xff1f; 直接在浏览器地址栏上输入URL。点击超链接提交form表单使用JS代码发送请求 window.open(url)document.location.href urlwindow.location.href url… 传统请…

面试总结-基础js

一、变量提升&#xff08;函数里面先形参赋值&#xff0c;再变量提升&#xff0c;最后执行代码&#xff09; 1、概念&#xff1a;当浏览器开辟出供代码执行的栈内存后&#xff0c;代码并没有自上而下立即执行&#xff0c;而是继续做了一些事情&#xff0c;把当前作用域所有带v…

C++基础编程100题-021 OpenJudge-1.4-01 判断数正负

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0104/01/ 描述 给定一个整数N&#xff0c;判断其正负。 输入 一个整数N(-109 < N < 109) 输出 如果N > 0, 输出positive; 如果N 0, 输出zero; 如果N < 0, 输出negative 样例输入 1样例输出…

【Linux】命令执行的判断依据:;,,||

在某些情况下&#xff0c;很多命令我想要一次输入去执行&#xff0c;而不想要分次执行时&#xff0c;该如何是好&#xff1f; 基本上有两个选择&#xff0c; 一个是通过shell脚本脚本去执行&#xff0c;一种则是通过下面的介绍来一次入多个命令。 1.cmd&#xff1a;cmd&#…

SAP EWM display message对话框长度限制

1.问题 使用标准方法/scwm/cl_rf_dynpro_srvc=>display_message显示消息文本,由于消息文本过长而被截取,影响显示效果 2.解决 通过调试跟踪当前标准方法,发现屏幕显示长度为40,最多显示4行,且iv_msg_text把每一行显示字段用空格拼接起来,故以下代码需要把显示消息…

Unity 打包的安卓APK在模拟器运行一会卡死

Unity 安卓APK模拟器运行一会卡死 如题&#xff0c;unity在模拟器上运行安卓apk挂机一会就卡死&#xff0c;在真机上没问题。因为打包时勾选了这个帧率优化选项&#xff0c;2019.2之后的功能&#xff0c;最坑的时打包时默认勾选&#xff0c;所以使用这个版本打包时&#xff0c…

如何写好品牌宣传稿提升品牌曝光?看这篇文章就够了

在这个信息爆炸的时代&#xff0c;一句精炼而富有力量的宣传语&#xff0c;足以让品牌在万千竞争者中脱颖而出。撰写一篇成功的品牌宣传稿&#xff0c;不仅是对文字艺术的驾驭&#xff0c;也是对品牌灵魂的深刻洞察与精准传达&#xff0c;更是连接品牌与消费者情感与认知的桥梁…

和鲸101计划夏令营火热进行中!北中医助阵医学数据探索

上周&#xff0c;和鲸社区 2024 夏令营已经正式开营&#xff01; 从 2021 年开始&#xff0c;和鲸社区在每年暑假期间都会为大家提供集中化、系统化的数据科学相关的技能实践和培训&#xff0c;每年都有几千名同学借此机会积累宝贵的实战经验&#xff0c;丰富个人简历作品&…

Apache功能配置:访问控制、日志分割; 部署AWStats日志分析工具

目录 保持连接 访问控制 只允许指定ip访问 拒绝指定主机其他正常访问 用户授权 日志格式 日志分割 操作步骤 使用第三方工具cronolog分割日志 AWStats日志分析 操作步骤 访问AwStats分析系统 保持连接 Apache通过设置配置文件httpd-default.conf中相关的连接保持参…