当前位置: 首页 > ai >正文

【Linux系统】条件变量

条件变量

  • 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
  • 例如一个线程访问队列时,发现队列为空,它只能等待,直到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量。

同步概念与竞态条件

  • 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源从而有效避免饥饿问题,叫做同步
  • 竞态条件:因为时序问题,而导致程序异常,我们称之为竞态条件。在线程场景下,这种问题也不难理解。
  • 互斥保证了安全性,但保证安全性的同时不一定能够安全可靠,同步主要是在保证安全性的情况下令线程调度更加高效可靠

条件变量函数

条件变量是用来进行线程同步的特性,内部要维护调度队列。

初始化

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
// 参数:
// cond: 要初始化的条件变量
// attr: NULL

销毁

int pthread_cond_destroy(pthread_cond_t *cond)

等待条件满足

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
// 参数:
// cond: 要在这个条件变量上等待
// mutex: 互斥量,后面详细解释

唤醒等待

int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒所有
int pthread_cond_signal(pthread_cond_t *cond);//唤醒一个

简单案例

  • 我们先使用PTHREAD_COND/MUTEX_INITIALIZER进行测试,对其他细节暂不追究
  • 然后将接口更改为使用pthread_cond_init/pthread_cond_destroy的方式,方便后续进行封装
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <pthread.h>pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void *active( void *arg ) {std::string name = static_cast<const char*>(arg);while (true){pthread_mutex_lock(&mutex);pthread_cond_wait(&cond, &mutex);std::cout << name << " 活动..." << std::endl;pthread_mutex_unlock(&mutex);}
}int main( void ) {pthread_t t1, t2;pthread_create(&t1, NULL, active, (void*)"thread-1");pthread_create(&t2, NULL, active, (void*)"thread-2");sleep(3); // 可有可无,这里确保两个线程已经在运行while(true) {// 对比测试// pthread_cond_signal(&cond); // 唤醒一个线程pthread_cond_broadcast(&cond); // 唤醒所有线程sleep(1);}pthread_join(t1, NULL);pthread_join(t2, NULL);
}

运行结果示例

$./cond
thread-1 活动...
thread-2 活动...
thread-1 活动...
thread-2 活动...

条件变量使用规范

等待条件代码

pthread_mutex_lock(&mutex);
while (条件不满足)pthread_cond_wait(cond, mutex);
修改条件代码
pthread_mutex_unlock(&mutex);

给条件发送信号代码

pthread_mutex_lock(&mutex);
设置条件为真signal(cond);
pthread_mutex_unlock(&mutex);
http://www.xdnf.cn/news/3818.html

相关文章:

  • Cona编译问题
  • Web网页布局
  • 赋予网页健壮的灵魂 —— TypeScript(下)
  • Circular Plot系列(五): circle plot展示单细胞互作
  • 电动调节V型球阀的作用:专为颗粒状含碱浆液介质打造的高效解决方案-耀圣
  • 第 14 届蓝桥杯 C++ 青少组省赛中 / 高级组真题解析
  • 开源项目:optimum-quanto库介绍
  • 全面掌握 Jetpack Compose 的 State 体系:核心用法与最佳实践
  • 动态规划(5)路径问题--剑指offer -珠宝的最大值
  • 7 微调 黑盒蒸馏 突破伦理限制
  • STM32外设-GPIO输入(仅数字)
  • [GESP202503 四级] 二阶矩阵c++
  • Spring AI 实战:第八章、Spring AI Tool Calling之与时俱进
  • Android Framework学习三:zygote剖析
  • 轻量化定时工具!Pt 极简界面 :定时备份 + 循环灵活关机
  • 基于springboot3+mybatis整合,使用mybatisPlus插件自动完成简单的 增删改查操作
  • LeetCode 热题 100 189. 轮转数组
  • 多语言笔记系列:Polyglot Notebooks 混合使用多语言并共享变量
  • 第三节:OpenCV 基础入门-安装与配置 OpenCV (Python/C++ 环境)
  • LeetCode 1128.等价多米诺骨牌对的数量:计数
  • 大连理工大学选修课——图形学:第五章 二维变换及二维观察
  • 多语言笔记系列:Polyglot Notebooks 多种使用方式
  • [2025]MySQL的事务机制是什么样的?redolog,undolog、binog三种日志的区别?二阶段提交是什么?ACID怎么保证的?主从复制的过程?
  • JVM happens-before 原则有哪些?
  • 利用KMP找出模式串在目标串中所有匹配位置的起始下标
  • 【25软考网工】第五章(4)ARP和RARP
  • 【Touching China】2007-2011
  • Go语言--语法基础4--基本数据类型--类型转换
  • MPI,Pthreads和OpenMP等并行实验环境配置
  • 【第三十四周】多模态大模型调研