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

在C语言中使用条件变量实现线程同步

互斥量、原子操作都是实现线程同步的方法,今日介绍使用条件变量来实现线程同步。在多线程应用中,当某个线程的执行依赖于另一个线程对数据的处理时,这个线程可能没有被阻塞,只是不断地检查某个条件是否成立了(这个条件就是另一个线程对数据处理的结果的指示器),这是一种“忙等待”的方式实现线程间的同步。在实践中应该避免使用,因为忙等待需要让线程反复检查某个条件是否为真,浪费大量宝贵的 CPU 资源在无用的活动上。使用条件变量既可以尽量减少处理器资源的浪费,又能够解决线程间数据依赖的问题。

C 标准库还提供了与条件变量相关的常用函数:

  • cnd_signal:发送条件变量,唤醒阻塞在cnd_wait调用处的线程
  • cnd_wait:阻塞线程,将线程加入等待队列,将会被cnd_signal唤醒
  • cnd_broadcast:唤醒所有在等待某个条件变量的线程
  • cnd_timedwait:带超时限制的cnd_wait

实例如下:

#include <threads.h>
#include <stdio.h>mtx_t mutex;// 互斥量
cnd_t cond; // 条件变量
int done = 0;
int run(void* arg){mtx_lock(&mutex);//加锁done = 1;cnd_signal(&cond);//发送条件信号mtx_unlock(&mutex);//解锁return thrd_success;
}int main(void){
#ifndef __STDC_NO_THREADS__mtx_init(&mutex,mtx_plain);//初始化互斥量cnd_init(&cond);//初始化条件变量thrd_t thread;thrd_create(&thread,run,NULL);//创建线程mtx_lock(&mutex);//加锁while(done == 0){cnd_wait(&cond,&mutex);//让当前线程进入等待队列,后续被唤醒后,互斥量会再次上锁}	mtx_unlock(&mutex);//解锁printf("The value of done is %d.\n",done);mtx_destroy(&mutex); cnd_destroy(&cond); // 销毁条件变量
#endifreturn 0;
}

在上述程序中,在 main 线程中,调用了与条件变量相关的函数 cnd_wait。该函数在被调用时,需要当前线程获得一个互斥锁,并将其作为实参传递给它,该函数调用后锁会被释放。同时,所有执行到此处的线程都将被阻塞。

子线程会执行run方法,run方法里会对done加1,然后调用函数 cnd_signal发送条件信号,唤醒所有之前被阻塞在函数 cnd_wait 处的线程,来让它们中的一个可以继续运行。在我们的例子中,只有 main 函数对应的一个线程,所以此时,互斥量将被重新上锁,main 线程将继续执行接下来的指令。

这样一来,某个线程可以在完成了某件事情后,通知并唤醒等待线程,让其继续工作,完成接下来的任务。而在此过程中,不需要线程频繁查询标志量。CPU 资源也得到了更好的利用。在并发编程中,通过条件变量,可以进一步实现监视器、管程等工具和同步原语。它也能够很好地解决生产者 - 消费者问题。

http://www.lryc.cn/news/530819.html

相关文章:

  • 图书管理系统 Axios 源码__新增图书
  • Maven全解析:从基础到精通的实战指南
  • 数据密码解锁之DeepSeek 和其他 AI 大模型对比的神秘面纱
  • python算法和数据结构刷题[5]:动态规划
  • Ollama+OpenWebUI部署本地大模型
  • Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍
  • 【网络】传输层协议TCP(重点)
  • 海思ISP开发说明
  • 实验十 Servlet(一)
  • doris:聚合模型的导入更新
  • Java NIO_非阻塞I/O的实现与优化
  • 代码随想录算法训练营Day51 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
  • Games202Lecture 6 Real-time Environment Mapping
  • 在 Zemax 中使用布尔对象创建光学光圈
  • MySQL知识点总结(十八)
  • [论文总结] 深度学习在农业领域应用论文笔记14
  • MySQL和Redis的区别
  • Rust 中的注释使用指南
  • 2025年2月2日(tcp3次握手4次挥手)
  • 一文了解制造业中的QC是什么
  • 【NEXT】网络编程——上传文件(不限于jpg/png/pdf/txt/doc等),或请求参数值是file类型时,调用在线服务接口
  • 在CentOS服务器上部署DeepSeek R1
  • 算法随笔_36: 复写零
  • MoonBit 编译器(留档学习)
  • 使用 DeepSeek-R1 与 AnythingLLM 搭建本地知识库
  • 网络工程师 (13)时间管理
  • 【xdoj-离散线上练习】T251(C++)
  • 定时器按键tim_key模版
  • Kanass快速安装配置教程(入门级)
  • 无用知识之:std::initializer_list的秘密