浅析linux下的条件变量
一.条件变量
条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。
当条件满足的时候,线程通常解锁并等待该条件发生变化,一旦另一个线程修改了环境变量,就会通知相应的环境变量唤醒一个或者多个被这个条件变量阻塞的线程。这些被唤醒的线程将重新上锁,并测试条件是否满足。一般来说条件变量被用于线程间的同步;当条件不满足的时候,允许其中的一个执行流挂起和等待。
条件变量中常用的API:
1).条件变量类型为:pthread_cond_t ,类似互斥变量,条件变量的初始化有两种方式:
静态:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;
动态:通过调用pthread_cond_init函数,函数原型为:
- 静态:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;
cond:环境变量.
attr:条件变量属性.
成功返回0,失败返回错误码.
2).条件变量摧毁函数:pthread_cond_destroy(&mycond);
- int pthread_cond_destroy(pthread_cond_t *cond);
成功返回0,失败返回错误码.
摧毁所指定的条件变量,同时将会释放所给它分配的资源。调用该函数的进程也并不等待在参数所指定的条件变量上。
3).条件变量等待函数。pthread_cond_wait(&mycond,&mylock);
- int pthread_cond_timedwait(pthread_cond_t *restrict cond,
- pthread_mutex_t *restrict mutex,
- const struct timespec *restrict abstime);
- int pthread_cond_wait(pthread_cond_t *restrict cond,
- pthread_mutex_t *restrict mutex);
cond:条件变量
mutex:互斥锁
pthread_cond_wait和pthread_cond_timedwait的区别:
pthread_cond_timedwait函数类型与函数pthread_cond_wait,区别在于,如果达到或是超过所引用的参数*abstime,它将结束并返回错误ETIME.
timespec
- typedef struct timespec
- {
- time_t tv_sec; //!> 秒
- long tv_nsex; //!> 毫秒
- }timespec_t;
当时间超过之前预设定的时会返回错误.
4).条件变量通知函数:pthread_cond_signal和pthread_cond_broadcast
- int pthread_cond_broadcast(pthread_cond_t *cond);
- int pthread_cond_signal(pthread_cond_t *cond);
pthread_cond_signal和pthread_cond_broadcast的区别:
pthread_cond_signal:只唤醒一个在相同条件变量中阻塞的线程将会被唤醒
pthread_cond_broadcast:唤醒等待队列中的所有线程
二.一个关于互斥锁和条件变量的栗子
栗子:用互斥锁和条件变量的概念实现一个简单的生产者和消费者的模型。
生产者和消费者模型:
1).满足互斥与同步条件,用互斥锁和条件变量实现
2).多个生产者和消费者:生产者和生产者属于互斥关系;生产者和消费者属于互斥和同步关系;消费者和消费者属于竞争关系,需要互斥锁
3).生产者和消费者模型中存在如下几种关系和角色:3种关系,2种角色,1种交换媒介(一般是一段内存)
下例以单生产者和单消费者,交换媒介为链表实现的生产者消费者模型
- procon.c
- #include<stdio.h>
- #include<stdlib.h>
- #include<assert.h>
- #include<pthread.h>
- typedef struct LinkNode
- {
- int data;
- struct LinkNode *next;
- }Node;
- pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t mycond=PTHREAD_COND_INITIALIZER;
- Node *CreatNode(int data)
- {
- Node *NewNode=(Node *)malloc(sizeof(Node));
- if(NULL == NewNode)
- {
- perror("malloc");
- return NULL;
- }
- NewNode->data=data;
- NewNode->next=NULL;
- return NewNode;
- }
- void InitLink(Node **head)
- {
- *head=CreatNode(0);
- }
- int IsEmpty(Node *head)
- {
- assert(head);
- if(head->next)
- return 0; //not empty
- else
- return 1; //empty
- }
- void PushFront(Node *head,int data)
- {
- assert(head);
- Node *NewNode=CreatNode(data);
- NewNode->next=head->next;
- head->next=NewNode;
- }
- void PopFront(Node *head,int *data)
- {
- assert(data);
- assert(head);
- if(IsEmpty(head))
- {
- printf("empty link\n");
- return ;
- }
- Node *del=head->next;
- *data=del->data;
- head->next=del->next;
- free(del);
- del=NULL;
- }
- void DisplayLink(Node *head)
- {
- assert(head);
- Node *cur=head->next;
- while(cur)
- {
- printf("%d ",cur->data);
- cur=cur->next;
- }
- printf("\n");
- }
- void DestroyLink(Node *head)
- {
- int data=0;
- assert(head);
- while(!IsEmpty(head))
- {
- PopFront(head,&data);
- }
- free(head);
- }
- void *product_run(void *arg)
- {
- int data=0;
- Node *head=(Node *)arg;
- while(1)
- {
- usleep(100000);
- data=rand()%1000;
- pthread_mutex_lock(&mylock);
- PushFront(head,data);
- pthread_mutex_unlock(&mylock);
- pthread_cond_signal(&mycond);
- printf("product is done,data=%d\n",data);
- }
- }
- void *consumer_run(void *arg)
- {
- int data=0;
- Node *head=(Node *)arg;
- while(1)
- {
- pthread_mutex_lock(&mylock);
- while(IsEmpty(head))
- {
- pthread_cond_wait(&mycond,&mylock);
- }
- PopFront(head,&data);
- pthread_mutex_unlock(&mylock);
- printf("consumer is done,data=%d\n",data);
- }
- }
- void testprocon()
- {
- Node *head=NULL;
- InitLink(&head);
- pthread_t tid1;
- pthread_t tid2;
- pthread_create(&tid1,NULL,product_run,(void *)head);
- pthread_create(&tid2,NULL,consumer_run,(void *)head);
- pthread_join(tid1,NULL);
- pthread_join(tid2,NULL);
- DestroyLink(head);
- pthread_mutex_destroy(&mylock);
- pthread_cond_destroy(&mycond);
- }
- int main()
- {
- testprocon();
- return 0;
- }
- Makefile
- procon:procon.c
- gcc -o $@ $^ -lpthread
- .PHONY:clean
- clean:
- rm -f procon
总结:
条件变量用在某个线程需要在某种条件才去保护它将要操作的临界区的情况下,从而避免了线程不断轮询检查该条件是否成立而降低效率的情况,这是实现了效率提高。
希望对读者有帮助吧~~~~
浅析linux下的条件变量相关推荐
- linux中的条件变量的使用
什么是条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制. 主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起:另一个线程使"条件成立"(给 ...
- linux下定义删除变量
linux下定义删除变量 linux中定义变量的方式为: 变量名=变量值(注意两边没有空格) a=123 //定义一个变量a,值为123 要使用变量的时候,要在变量前面加 ...
- linux下配置环境变量方式
linux下配置环境变量有多种方式,下面简述之 方式1.编辑 /etc/profile 文件,增加如下内容 JAVA_HOME=/usr/local/jdk1.8 export JAVA_HOME P ...
- Linux下修改环境变量
刚接触Linux,记录一下Linux下修改环境变量的过程. 首先切换到root用户. (1)打开profile文件 ①通过vim打开 vim /etc/profile ②通过文本编辑器打开 gedit ...
- mtd分区创建linux,浅析linux下mtd设备onenand存储器的分区和节点创建流程及yaffs2文件系统挂载...
浅析linux下mtd设备onenand存储器的分区和节点创建流程及yaffs2文件系统挂载 在arch/arm/mach-pxa/luther.c这个产品平台文件中,即: MACHINE_START ...
- 嵌入式 linux usbmon,浅析linux下替代usbhound的usb总线sniffer抓包模块usbmon安装和使用...
浅析linux下替代usbhound的usb总线sniffer抓包模块usbmon安装和使用 操作系统: ubuntu 8.10 内核版本: 2.6.27-7-generic ubuntu 8.10内 ...
- linux下jdk环境变量配置深度分析----解决环境变量不生效的问题
1.linux下jdk环境变量配置 是否需要配置环境变量,主要看java -version 显示的版本是否为你期望的版本 1.1 不需要配置环境变量的情况 使用java -version查看,版本显示 ...
- 嵌入式 Linux 入门(七、Linux 下的环境变量)
嵌入式 Linux 入门第七课,学习理解 linux 的环境变量 ......矜辰所致 前言 学习完 Linux 的 Shell 命令 和 Shell 脚本,我们还需要理解一个东西 :环境变量,理解了 ...
- Linux多线程同步------条件变量
先来看下<Linux高性能服务器编程>中对条件变量的描述: 上述话可以总结为: 多线程中某一个线程依赖于另外一个线程对共享数据的改变时,就可以使用条件变量! 用消费者生产者的来理解条件变量 ...
最新文章
- 深度解析机器学习中的置信区间(附代码)
- 张钹院士:制约人工智能发展的最大困难是什么?
- zookeeper 分布式计数器
- 织梦 m list.php tid,在织梦标签dede:list中增加noflag属性的方法支持5.7版本
- matlab 如何定义符号数组
- 清除word中超链接
- 处理本地能登陆mysql但navicat连接不上的问题
- 今天诛仙3服务器维护么2014年4月27,诛仙2021年3月4日更新维护公告 诛仙2021年3月4日更新维护内容一览_手心游戏...
- Excel2007中插入页眉和页脚
- c#异步文件传输功能
- Atitit s2018.2 s2 doc list on home ntpc.docx \Atiitt uke制度体系 法律 法规 规章 条例 国王诏书.docx \Atiitt 手写文字
- 解决报错:错误使用 xlsread未找到工作表 ‘sheet1‘
- 90后最流行的英文名
- 2022年化肥行业发展趋势
- 小米冲高端?差了几口气
- 天梯图excl_Excel版CPU天梯图 方便打印.xls
- 上周NFT销售CryptoPunk囊括前三
- 对计算机系美好期望,计算机系举行新生入学教育大会——学生讲堂
- c#语言中if语句多条件,关于C# if语句中并列条件的执行
- 【ABAP】采购订单行项目 税码 自动默认
热门文章
- yaml,json,ini这三种格式用来做配置文件优缺点
- ZOJ Monthly, November 2012
- WinForm------TextEdit只能输入数字
- 网站上flv,MP4等格式的视频文件播放不出来的解决办法
- 初步体验数据驱动之美---TreeView
- 强大js web甘特图制作之甘特图组件和数据对象
- oracle group by 多类别_python数据关系型图表散点图系列多数据系列
- html vbs 输入框,HTML_vbs实现的下拉框对应键入值,vbs实现的下拉框对应键入值 - phpStudy...
- 经过路由无法找到计算机,电脑无法启动服务提示系统找不到指定的路径(图)
- vue 分模块打包 脚手架_Vue面试官最爱的底层源码问题,你可以这样回答!