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

条件变量的基本介绍与有界缓冲区问题

条件变量

多数情况下,线程需要检查某一条件是否满足之后,才会继续运行。

线程可以使用条件变量来等待一个条件变成真。条件变量是一个显式队列,当某些条件不满足时线程可以把自己加入队列,等待该条件。另外某个线程改变了上述条件时,就可以唤醒一个或多个等待线程,让它们继续执行。

//该函数用于使线程睡眠
pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
{//互斥量参数的意义://该函数假定在被调用时该互斥量是已上锁的状态,wait函数负责释放锁,并让//调用线程休眠。当线程被唤醒时,该函数必须重新获取锁,再返回给调用者//这样做的目的是为了避免在线程休眠时产生一些竟态条件
}//该函数用于唤醒线程
pthread_cond_signal(pthread_cond_t  *c)
{} //状态变量,标志着子线程是否完成
int done = 0; pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t c = PTHREAD_COND_INITIALIZER; void thr_exit() {Pthread_mutex_lock(&m); done = 1; Pthread_cond_signal(&c); Pthread_mutex_unlock(&m); } void *child(void *arg) { printf("child\n"); //子线程退出并唤醒父线程thr_exit();return NULL; 
} void thr_join() { //获取锁Pthread_mutex_lock(&m); //检查子线程是否完成,未完成则使父线程休眠,这里的done变量是必须的//这里使用while循环比if好while (done == 0) Pthread_cond_wait(&c, &m);//此时子线程得以运行//从wait返回时持有锁,此时释放锁Pthread_mutex_unlock(&m); 
} int main(int argc, char *argv[]) { printf("parent: begin\n"); pthread_t p;//创建子线程Pthread_create(&p, NULL, child, NULL); //使子线程运行thr_join(); printf("parent: end\n"); return 0; 
}

如果没有done变量,假设子线程先运行,那么父线程就永远得不到运行。done变量记录了线程的状态,是必须的。

假设在join函数中没有互斥量,那么会产生一个竟态条件。父线程在子线程前运行,在即将调用wait函数时,发生了中断使子线程运行。子线程修改done为1,并发送信号使徒唤醒父线程,但是此时父线程在休眠之前被中断了,它并没有处于休眠状态,所以父线程永远不会被唤醒。

总结以下就是发送信号时总是持有锁。

生产者/消费者(有界缓冲区)问题

假设有一个或多个生产者线程和一个或多个消费者线程。生产者把生成的数据项放入缓冲区;消费者从缓冲区取走数据项,以某种方式消费。因为有界缓冲区是共享资源,所以我们必须通过同步机制来访问它,以免产生竞态条件。

//使用一个整形变量来代表缓冲区
int buffer; //该变量用于辨识缓冲区中是否有数据,0为空,1为满
int count = 0; // initially, empty void put(int value) { assert(count == 0); count = 1; buffer = value; 
} int get() { assert(count == 1); count = 0; return buffer; 
} 

发信号给线程只是唤醒它们,暗示状态发生了变化,但并不会保证在它运行之前状态一直是期望的情况。信号的这种释义常称为 Mesa 语义(Mesa semantic),为了纪念以这种方式建立条件变量的首次研究。另一种释义是 Hoare 语义(Hoare semantic),虽然实现难度大,但是会保证被唤醒线程立刻执行。实际上,几乎所有系统都采用了Mesa语义。

关于最终的有界缓冲区问题解决方案,是使用while、两个条件变量,并让生产者在缓冲区满时休眠,让消费者在缓冲区空时休眠。

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

相关文章:

  • 小红书帖子评论的nodejs爬虫脚本
  • 补充日志之-配置文件解析指南(Centos7)
  • CAXA电子图板2026(国产CAD之光)
  • 机器学习之PCA
  • pyqt5无法显示opencv绘制文本和掩码信息
  • OpenCV 阈值处理
  • 应用侧华为云LoTDA设备接入平台
  • 重塑工业设备制造格局:明远智睿 T113-i 的破局之道
  • IgH初始化--未接从站
  • 【160页PPT】机械行业数字化生产供应链产品解决方案(附下载方式)
  • 光伏工单智能管理,故障处理快人一步
  • 状态流程框架(cola-component-statemachine)
  • WinForm 简单用户登录记录器实现教程
  • 五、ZooKeeper、Kafka、Hadoop、HBase、Spark、Flink集群化软件的部署
  • Sui 主网升级至 V1.53.2
  • 【DDIA】第三部分:衍生数据
  • 俄罗斯信封套娃问题-二维最长递增子序列
  • day29-进程和线程(2)
  • python自学笔记9 Seaborn可视化
  • 47.分布式事务理论
  • Elasticsearch:使用 Gradio 来创建一个简单的 RAG 应用界面
  • LeetCode刷题记录----236.二叉树的最近公共节点(medium)
  • 终极手撸cpu系列-详解底层原理-CPU硬核解剖:从0和1到 看透CPU逻辑设计内部原理,弄清楚现代多线程cpu工作原理
  • IC(Integrated Circuit,集成电路)是什么?
  • Qt——常用Widget(控件)
  • 数据结构初阶(17)排序算法——非比较排序、排序算法总结
  • Git、JSON、MQTT
  • 【Javaweb学习|黑马笔记|Day1】初识,入门网页,HTML-CSS|常见的标签和样式|标题排版和样式、正文排版和样式
  • 混凝土抗压强度预测:基于机器学习的全流程实战解析​
  • flume实战:从零配置到启动运行的完整指南