POSIX条件变量API函数

初始化条件变量

int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);

返回值:函数成功返回0;任何其他返回值都表示错误

初始化一个条件变量。当参数attr为空指针时,函数创建的是一个缺省的条件变量。

阻塞

int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);

wait需要传入已经lock的mutex变量。进入wait函数会自动解锁mutex参数指向的互斥锁,并使当前线程阻塞在cond参数指向的条件变量上。当线程被唤醒,退出wait函数时会自动对锁再次进行加锁,成功后返回。

被阻塞的线程可以被pthread_cond_signal函数,pthread_cond_broadcast函数唤醒。一般一个条件表达式都是在一个互斥锁的保护下被检查。当条件表达式未被满足时,线程将仍然阻塞在这个条件变量上。当另一个线程改变了条件的值并向条件变量发出信号时,等待在这个条件变量上的一个线程或所有线程被唤醒,接着都试图再次占有相应的互斥锁。

int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, const structtimespec * abstime);

函数到了一定的时间,即使条件未发生也会解除阻塞。这个时间由参数abstime指定。

唤醒

int pthread_cond_signal(pthread_cond_t *cond);

函数被用来释放被阻塞在指定条件变量上的一个线程。唤醒阻塞在条件变量上的所有线程的顺序由调度策略决定,如果线程的调度策略是SCHED_OTHER类型的,系统将根据线程的优先级唤醒线程。

int pthread_cond_broadcast(pthread_cond_t *cond);

函数唤醒所有被pthread_cond_wait函数阻塞在某个条件变量上的线程,参数cond被用来指定这个条件变量。

释放条件变量

int pthread_cond_destroy(pthread_cond_t *cond);

一个例子:

#include <stdio.h>#include <pthread.h>#include <unistd.h>pthread_mutex_t count_lock;pthread_cond_t count_nonzero;unsigned count = 0;void *decrement_count(void *arg){pthread_mutex_lock(&count_lock);printf("decrement_count get count_lock/n");while(count == 0){printf("decrement_count count == 0 /n");printf("decrement_count before cond_wait /n");pthread_cond_wait(&count_nonzero, &count_lock);printf("decrement_count after cond_wait /n");}count = count - 1;pthread_mutex_unlock(&count_lock);}void *increment_count(void *arg){pthread_mutex_lock(&count_lock);printf("increment_count get count_lock /n");if(count == 0){printf("increment_count before cond_signal /n");pthread_cond_signal(&count_nonzero);printf("increment_count after cond_signal /n");}count = count + 1;pthread_mutex_unlock(&count_lock);}int main(void){pthread_t tid1, tid2;pthread_mutex_init(&count_lock, NULL);pthread_cond_init(&count_nonzero, NULL);pthread_create(&tid1, NULL, decrement_count, NULL);sleep(2);pthread_create(&tid2, NULL, increment_count, NULL);sleep(10);pthread_exit(0);return 0;}

运行结果:

decrement_count get count_lock
decrement_count count == 0 
decrement_count before cond_wait 
increment_count get count_lock 
increment_count before cond_signal 
increment_count after cond_signal 
decrement_count after cond_wait

调试程序的运行过程:

1、开始时 counter 为0 (main)

2、首先生成一个thrd1线程运行decrement_counter(),此线程内函数运行流程为:

先锁定 互斥锁(count_lock) 如果counter为0,此线程被阻塞在条件变量(count_nonzero)上.同时释放互斥锁count_lock(wait函数内部会先释放锁,等待signal激活后自动再加上锁).

3、与此同时主程序还在运行,创建另一个线程thrd2运行 increment_counter,此线程内的函数流程如下:

先锁定 互斥锁(count_lock)(wait内部释放锁的互斥锁) 如果counter为0, 唤醒在条件变量(count_nonzero)上的线程即thrd1.但是由于互斥锁count_lock被当前thrd2锁住(signal激活后,线程1的wait内部需要对count_lock上锁, thrd1还是在等待. 然后thrd2中对count+1,释放互斥锁。此时thrd1由于互斥锁释放得以运行,重新判断counter是不是为0,如果为0再把线程阻塞在条件变量count_nonzero上,但这时counter已经为1了.所以线程继续运行.counter-1释放互斥锁(退出后,运行主线程main

生产者消费者例子:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>#define ERR_EXIT(m)\do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)#define CONSUMERS_COUNT 2
#define PRODUCERS_COUNT 1pthread_mutex_t g_mutex;
pthread_cond_t g_cont;int iread;pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];void* produce(void* arg)
{while(1){pthread_mutex_lock(&g_mutex);iread++;	//生产printf("product iread=%d\n",iread);pthread_cond_signal(&g_cont);printf("produce is produat\n");pthread_mutex_unlock(&g_mutex);sleep(3);}return NULL;
}
void* consumer(void* arg)
{while(1){pthread_mutex_lock(&g_mutex);printf("consumer iread =%d\n",iread);	while(iread==0)  //需要等待生产者生产{pthread_cond_wait(&g_cont, &g_mutex);printf("iread is changed\n");}iread--;  //消费sleep(1);pthread_mutex_unlock(&g_mutex);}return NULL;
} int main()
{int i;pthread_mutex_init(&g_mutex,NULL);pthread_cond_init(&g_cont,NULL);for(i=0; i< PRODUCERS_COUNT;i++){pthread_create(&g_thread[i],NULL,produce,(void*)i);}for(i=0; i< CONSUMERS_COUNT;i++){pthread_create(&g_thread[i+ PRODUCERS_COUNT],NULL,consumer,(void*)i);}for(i=0; i< PRODUCERS_COUNT+CONSUMERS_COUNT;i++){pthread_join(g_thread[i],NULL);}pthread_mutex_destroy(&g_mutex);pthread_cond_destroy(&g_cont);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/490197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阶段性思考

算上在学校&#xff0c;学习前端已经两年了&#xff0c;但水平依旧不高&#xff0c;至今都只愿意钻研布局和交互&#xff0c;把兼容和动效玩得哈皮&#xff0c;但其实依旧没有装逼的自信。 也不得不回到当初的那个思考&#xff0c;如果只是做网页&#xff0c;又何必弄前端&…

反弹式木马原理_汽车避震器的原理与改装问题

一、避震器or避振器“震”字是指车轮在路面的滚动过程中&#xff0c;由于路面的不平&#xff0c;从路面传递上来的震动&#xff0c;而不是人为制造“振”动&#xff0c;所以使用“震”字更科学。二、避震器的工作原理避震器的工作原理是通过活塞运动产生阻尼力&#xff0c;将动…

科学探索奖首批50名获奖者都有谁?

来源&#xff1a;知识分子9月20日上午&#xff0c;经过四个多月的评审&#xff0c;2019年 获奖名单正式公布。来自全国26个科研单位、高校和企业的50位科学家成为首届“科学探索奖”获奖者&#xff0c;每人将在未来5年获得由腾讯基金会资助的300万元人民币。据悉&#xff0c;20…

python_递归原理

需要:  输出这样一些有规律数据: [0,1,1,2,3,5,8,13,21,34.......]看上面需要好像有一些规律&#xff0c;没错&#xff0c;就是大家熟悉的婓那波契数列,n(n-1)(n-2)如1385&#xff1b;运用递归原理得:def func(arg1,arg2): if arg1 0: print arg1,arg2 arg3 a…

POSIX信号量API函数

头文件&#xff1a;semaphore.h 初始化&#xff1a; int sem_init(sem_t *sem, int pshared, unsigned int value); sem_init() 初始化一个信号量&#xff0c;信号量对象为sem。value 参数指定信号量的初始值。 pshared 参数指明信号量是由进程内线程共享&#xff0c;还是由…

untitled软件怎么用_苹果手机怎么用4G网络于App Store下载超过200MB以上的软件

近两年来&#xff0c;随着苹果中国市场份额被国产品牌挤占了不少&#xff0c;他们越来越懂得“聆听”中国用家的需要&#xff0c;其中一项便是用手机网络(4G)下载iOS应用。在这一点上我们中国人也不用再妄自菲薄了&#xff0c;在疯狂的4G建网以后&#xff0c;我们国家已经拥有全…

关于人脸识别的最全研究!

来源&#xff1a;北京物联网智能技术应用协会本文内容涵盖人脸识别发展历程、市场研究、核心技术、商业应用以及产业落地、个人看法等干货研究。注意&#xff0c;本文干货满满&#xff0c;约有2万7千字&#xff0c;强烈建议大家先收藏后学习&#xff01;01 发展史1. 人脸识别的…

Stream学习过程中遇到的一个问题记录

Stream学习过程中遇到的一个问题记录 Test public void stream_modifiedV2(){List<String> strings Arrays.asList("aaa","bb","cc","dddddddddddddddddddddddddddddddd");Stream<String> stringStream strings.stream(…

C++ swap用法

swap用于交换两个元素的值 template<class T> void swap(T &a,T &b) {T c(a);ab;bc; } 例如交换两个int型变量的值&#xff1a; #include <iostream> using namespace std;int main() {int a1,b2;swap(a,b);cout<<a<<" "<<…

python table类中的 可以作为初步观察工具_Python程序设计基础_课程2020最新章节测试网课课后答案...

Python程序设计基础_课程2020最新章节测试网课课后答案更多相关问题科学探究的过程一般要经过______、作出假设、制定方案、实施方案&#xff0c;得出结论等五个步骤&#xff0e;在生物学研究中&#xff0c;当实验的结果与原有的知识发生矛盾时&#xff0c;应大胆地修正原有的知…

关于字节对齐以及内存占用

参考博文&#xff1a; http://www.javamex.com/tutorials/memory/object_memory_usage.shtml 本文主要考虑正常情况下一个对象在堆上的内存占用情况&#xff1a;对于下面的特殊情况不作讨论 1、某些情况下&#xff0c;JVM可能不会把对象存储在堆上&#xff1a;比如小的线程私有…

人工智能应用实践与趋势

来源&#xff1a;阿里云研究中心《崛起的超级智能》一书主要阐述当今天人类为人工智能的春天到来而兴奋&#xff0c;为人工智能是否超越人类而恐慌的时候&#xff0c;一个更为庞大、远超人类预期的智能形态正在崛起&#xff0c;种种迹象表明50年来&#xff0c;互联网正在从网状…

C++中set和map的erase用法

删除容器中值为 val 的元素 size_type erase (const value_type& val); 删除 it迭代器指向的元素 iterator erase (const_iterator it); 删除 [first,last) 区间内的所有元素 iterator erase (const_iterator first, const_iterator last);

excel表格打印每页都有表头_这么漂亮的Excel表格,用黑白打印机打印真是可惜了...

我们在日常工作中&#xff0c;利用Excel制作的表格通过会填充颜色&#xff0c;设置字体和边框格式、颜色&#xff0c;把表格弄的漂漂亮亮的&#xff0c;一个是为了缓解视觉疲劳&#xff0c;另一个是为了老板看到漂亮的表格一不小心加工资呢&#xff0c;但是一个问题出来了&…

常用的分隔符有哪三种_加固博士:常用防水材料大比拼,究竟花落谁家?

建筑物漏水问题&#xff0c;是日常生活中非常常见的问题&#xff0c;房屋漏水怎么办才好呢&#xff1f;这个问题困扰了很多人&#xff0c;有些户主会图个省事&#xff0c;将漏水问题直接交给装修公司&#xff0c;只要愿意支付防水施工费用&#xff0c;装修公司就会安排资深的师…

svg笔记----------path篇

每个路径都必须以moveto 命令开始 moveto、lineto和closepath <path d"M 10 10 L 100 10z"/> 大写字母命令的坐标是绝对的&#xff0c;小写字母命令的坐标是相对的。其它情况&#xff1a; 1.z(closepath)命令没有坐标&#xff0c;它的大小写形式效果相同。 2.如…

互联网大脑,城市大脑的“大脑”究竟什么含义?

来源&#xff1a;刘锋的未来课堂21世纪以来&#xff0c;科技领域与一个神经学领域的概念 “大脑”出现了意外的结合&#xff0c;涌现出诸多前沿科技的大脑概念。从互联网大脑&#xff0c;城市大脑&#xff0c;到谷歌大脑&#xff0c;百度大脑&#xff0c;讯飞超脑、360安全大脑…

C++ lower_bound和upper_bound的区别

lower_bound( begin,end,num)&#xff1a;返回第一个大于等于参数num的迭代器 upper_bound( begin,end,num)&#xff1a;返回第一个大于参数num的迭代器 > 和> 是二者的区别

电脑fps低怎么办_电脑想要英雄联盟玩的流畅,主要看哪几个方面?

刚刚在找素材的时候&#xff0c;看到有个兄弟在某乎上说打英雄联盟有点卡&#xff0c;换个固态硬盘能不能提升游戏体验。在看到这个问题之后&#xff0c;小编发现原来还有很多电脑小白不知道什么东西会影响游戏体验。所以今天我就大概说一下玩英雄联盟这款游戏看重的地方吧。小…

python迷宫求解代码_Python中的迷宫求解

我孜孜不倦地试图用python制作一个迷宫解算器。我已经使用了我所有的资源&#xff0c;比如朋友、互联网和堆栈。我已经根据之前的堆栈问题修改了很多代码&#xff0c;但是即使完全复制代码(我不喜欢这样做)&#xff0c;也无法得到答案。在迷宫/输入文件(嵌套列表)&#xff1a;[…