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

在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); // 销毁条件变量
#endif
	return 0;
}

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

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

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


http://www.kler.cn/a/529663.html

相关文章:

  • taro遇到的问题
  • LeetCode:300.最长递增子序列
  • Node.js 和 npm 安装教程
  • 【ts + java】古玩系统开发总结
  • 【机器学习】自定义数据集 ,使用朴素贝叶斯对其进行分类
  • 几种K8s运维管理平台对比说明
  • w187社区养老服务平台的设计与实现
  • M|哪吒之魔童闹海
  • 【网络】传输层协议TCP(重点)
  • Python虚拟环境
  • Redis万字面试题汇总
  • 虚幻基础16:locomotion direction
  • 使用ollama在本地部署一个deepseek大模型
  • 面渣逆袭之Java基础篇3
  • LLMs之DeepSeek:Math-To-Manim的简介(包括DeepSeek R1-Zero的详解)、安装和使用方法、案例应用之详细攻略
  • XML DOM 节点
  • 详解Kafka并行计算架构
  • 深入了解 ls 命令及其选项
  • 【AI】探索自然语言处理(NLP):从基础到前沿技术及代码实践
  • unity免费资源2025-2-2
  • 涡旋光特性及多种模型、涡旋光仿真
  • final-关键字
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>单词搜索
  • wax到底是什么意思
  • 【高级篇 / IPv6】(7.6) ❀ 03. 宽带IPv6 - ADSL拨号宽带上网配置 ❀ FortiGate 防火墙
  • 53. Uboot命令使用