linux C++ 多线程使用pthread_cond 条件变量
1. 背景
多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的互斥操作。
但是互斥锁有一个明显到缺点: 只有两种状态,锁定和非锁定。
而条件变量则通过允许线程阻塞并等待另一个线程发送唤醒信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。
2. 条件变量涉及到的主要函数
2.1 pthread_cond_wait 线程阻塞在条件变量
int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex);
函数将解锁mutex参数指向的互斥锁,并使当前线程阻塞在cv参数指向的条件变量上。被阻塞的线程可以被pthread_cond_signal函数,pthread_cond_broadcast函数唤醒,也可能在被信号中断后被唤醒。pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回。pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值。最好的测试方法是循环调用pthread_cond_wait函数,并把满足条件的表达式置为循环的终止条件。
1 pthread_mutex_lock(); 2 while (condition_is_false) 3 pthread_cond_wait(); 4 pthread_mutex_unlock();
阻塞在同一个条件变量上的不同线程被唤醒的次序是不一定的。
2.2 pthread_cond_signal 线程被唤醒
int pthread_cond_signal(pthread_cond_t *cv);函数被用来释放被阻塞在指定条件变量上的一个线程。必须在互斥锁的保护下使用相应的条件变量。否则对条件变量的解锁有可能发生在锁定条件变量之前,从而造成死锁。唤醒阻塞在条件变量上的所有线程的顺序由调度策略决定,如果线程的调度策略是SCHED_OTHER类型的,系统将根据线程的优先级唤醒线程。如果没有线程被阻塞在条件变量上,那么调用pthread_cond_signal()将没有作用。
更多函数可以看: http://blog.csdn.net/icechenbing/article/details/7662026
3. 实例代码
实现功能: 2个线程对count每次分别加1, 第三个线程等count大于10后一次加100.
3.1 加1线程函数
1 void *inc_count(void *idp) 2 { 3 int i = 0; 4 int taskid = 0; 5 int *my_id = (int*)idp; 6 7 for (i=0; i<TCOUNT; i++) { 8 pthread_mutex_lock(&count_mutex); 9 taskid = count; 10 count++; 11 12 /* 13 唤醒一个阻塞在该条件变量到线程 14 如果没有线程被阻塞在条件变量上,那么调用pthread_cond_signal()将没有作用 15 */ 16 pthread_cond_signal(&count_threshold_cv); 17 18 printf("inc_count(): thread %d, count = %d, unlocking mutex\n", *my_id, count); 19 pthread_mutex_unlock(&count_mutex); 20 sleep(1); 21 } 22 printf("inc_count(): thread %d, Threshold reached.\n", *my_id); 23 24 pthread_exit(NULL); 25 }
3.2 count满足条件后, 单次加100函数
1 void *watch_count(void *idp) 2 { 3 int *my_id = (int*)idp; 4 printf("Starting watch_count(): thread %d\n", *my_id); 5 6 pthread_mutex_lock(&count_mutex); 7 while(count<COUNT_LIMIT) { 8 sleep(3); 9 /* 10 函数将自动/原子的解锁count_mutex参数指向的互斥锁,并使当前线程阻塞在cv参数指向的条件变量上 11 被阻塞的线程可以被pthread_cond_signal函数,pthread_cond_broadcast函数唤醒,也可能在被信号中断后被唤醒 12 pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值. 13 本例子中线程被唤醒后, 仍然在while内会再次判断COUNT_LIMIT是否满足条件的值 14 pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回 15 */ 16 pthread_cond_wait(&count_threshold_cv, &count_mutex); 17 printf("watch_count(): thread %d Condition signal received.\n", *my_id); 18 } 19 20 count += 100; 21 pthread_mutex_unlock(&count_mutex); 22 pthread_exit(NULL); 23 }
3.3 整体代码
1 #include <pthread.h> 2 #include <stdio.h> 3 #include <unistd.h> 4 5 #define NUM_THREADS 3 6 #define TCOUNT 10 7 #define COUNT_LIMIT 10 8 9 int count = 0; 10 int thread_ids[3] = {0,1,2}; 11 pthread_mutex_t count_mutex; 12 pthread_cond_t count_threshold_cv; 13 14 void *inc_count(void *idp) 15 { 16 int i = 0; 17 int taskid = 0; 18 int *my_id = (int*)idp; 19 20 for (i=0; i<TCOUNT; i++) { 21 pthread_mutex_lock(&count_mutex); 22 taskid = count; 23 count++; 24 25 /* 26 唤醒一个阻塞在该条件变量到线程 27 如果没有线程被阻塞在条件变量上,那么调用pthread_cond_signal()将没有作用 28 */ 29 pthread_cond_signal(&count_threshold_cv); 30 31 printf("inc_count(): thread %d, count = %d, unlocking mutex\n", *my_id, count); 32 pthread_mutex_unlock(&count_mutex); 33 sleep(1); 34 } 35 printf("inc_count(): thread %d, Threshold reached.\n", *my_id); 36 37 pthread_exit(NULL); 38 } 39 40 void *watch_count(void *idp) 41 { 42 int *my_id = (int*)idp; 43 printf("Starting watch_count(): thread %d\n", *my_id); 44 45 pthread_mutex_lock(&count_mutex); 46 while(count<COUNT_LIMIT) { 47 sleep(3); 48 /* 49 函数将自动/原子到解锁mutex参数指向的互斥锁,并使当前线程阻塞在cv参数指向的条件变量上 50 被阻塞的线程可以被pthread_cond_signal函数,pthread_cond_broadcast函数唤醒,也可能在被信号中断后被唤醒 51 pthread_cond_wait函数的返回并不意味着条件的值一定发生了变化,必须重新检查条件的值. 52 本例子中使用类COUNT_LIMIT最为满足条件的值 53 pthread_cond_wait函数返回时,相应的互斥锁将被当前线程锁定,即使是函数出错返回 54 */ 55 pthread_cond_wait(&count_threshold_cv, &count_mutex); 56 printf("watch_count(): thread %d Condition signal received.\n", *my_id); 57 } 58 59 count += 100; 60 pthread_mutex_unlock(&count_mutex); 61 pthread_exit(NULL); 62 } 63 64 int main (int argc, char *argv[]) 65 { 66 int i, rc; 67 pthread_t threads[3]; 68 pthread_attr_t attr; 69 70 /* Initialize mutex and condition variable objects */ 71 pthread_mutex_init(&count_mutex, NULL); 72 pthread_cond_init (&count_threshold_cv, NULL); 73 74 /* For portability, explicitly create threads in a joinable state */ 75 pthread_attr_init(&attr); 76 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 77 pthread_create(&threads[0], &attr, inc_count, (void *)&thread_ids[0]); 78 pthread_create(&threads[1], &attr, inc_count, (void *)&thread_ids[1]); 79 pthread_create(&threads[2], &attr, watch_count, (void *)&thread_ids[2]); 80 81 /* Wait for all threads to complete */ 82 for (i=0; i<NUM_THREADS; i++) { 83 pthread_join(threads[i], NULL); 84 } 85 printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS); 86 87 /* Clean up and exit */ 88 pthread_attr_destroy(&attr); 89 pthread_mutex_destroy(&count_mutex); 90 pthread_cond_destroy(&count_threshold_cv); 91 pthread_exit(NULL); 92 93 return 0; 94 }
View Code
转载于:https://www.cnblogs.com/xudong-bupt/p/6707070.html
linux C++ 多线程使用pthread_cond 条件变量相关推荐
- Linux下互斥量与条件变量详细解析
1. 首先pthread_cond_wait 的定义是这样的 The pthread_cond_wait() and pthread_cond_timedwait() functions are us ...
- Linux系统编程---17(条件变量及其函数,生产者消费者条件变量模型,生产者与消费者模型(线程安全队列),条件变量优点,信号量及其主要函数,信号量与条件变量的区别,)
条件变量 条件变量本身不是锁!但它也可以造成线程阻塞.通常与互斥锁配合使用.给多线程提供一个会合的场所. 主要应用函数: pthread_cond_init 函数 pthread_cond_destr ...
- C++多线程编程(2) 条件变量与原子操作
条件变量 条件变量是c++11 提供的另一种用于等待的同步机制,它能阻塞一个或者多个线程,直到收到另外一个线程发出的通知或者超时,才会唤醒当前阻塞的线程,条件变量需要和互斥量配合使用,C++11提供两 ...
- java suprious wakeup_多线程编程中条件变量和的spurious wakeup 虚假唤醒
1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1)线程等待某 ...
- 【多线程】1.条件变量--std::condition_variable
条件变量允许我们通过通知进而实现线程同步. 因此,您可以实现发送方/接收方或生产者/消费者之类的工作流. 在这样的工作流程中,接收者正在等待发送者的通知.如果接收者收到通知,它将继续工作. 1. st ...
- python多线程编程(5): 条件变量同步
From: http://www.cnblogs.com/holbrook/archive/2012/03/13/2394811.html 互斥锁是最简单的线程同步机制,Python提供的Condit ...
- c++多线程基础4(条件变量)
条件变量是允许多个线程相互交流的同步原语.它允许一定量的线程等待(可以定时)另一线程的提醒,然后再继续.条件变量始终关联到一个互斥 定义于头文件 <condition_variable> ...
- posix多线程程序使用条件变量的一个常见bug
因为类似的问题至少碰到3次以上,虽然很简单但是每次都花了不少时间来定位,所以决定写个demo来演示一下:)程序逻辑比较简单,主线程读入一个整数,分别有两个线程对这个整数求1~n的累加和.代码如下: 1 ...
- linux条件变量唤醒丢失,多线程编程精髓(三)
本篇主要讲Linux环境下的多线程同步内核对象. (1)linux线程同步之互斥体:linux互斥体的用法与windows的临界区对象类似,使用数据结构 pthread_mutex_t表示互斥体对象( ...
最新文章
- linux进程间通信:system V 信号量 生产者和消费者模型编程案例
- 为asa防火墙配置ssh登陆
- 三十二、图的创建深度优先遍历(DFS)广度优先遍历(BFS)
- onnxruntime c++ 工程实例
- CentOS 6.3定制自动安装
- WPF 根据绑定值设置DataGrid行背景色
- html h1 字母,html----h1-6标签
- Imdb影评的数据集介绍与下载
- FTP服务器构建与维护,ftp服务器的搭建与三种访问途径
- Linux查ip出来的pp0,linux下使用shell查看apache IP访问量
- 快速幂算法(矩阵快速幂还不是很会。。日后会更新)
- python机器学习-乳腺癌细胞挖掘
- 配音软件文字转语音有哪些?
- 品优购电商系统 1 - 分布式框架Dubbox
- 自制抖音去水印工具 java+微信小程序
- H5唤起主流安卓应用市场
- android版本和基带版本号,安卓手机基带是什么意思?基带版本之间有什么区别?...
- 住得越高越安静? 中间楼层噪音最大
- 人生的思考——温水中被煮熟的程序员
- linux密码安全加固技术-CKEY动态密码技术【顶】
热门文章
- postman发送object_.NetCore HttpClient发送请求的时候为什么自动带上了一个RequestId头部...
- oracle查询表字段sql语句怎么写,oracle联合查询并更新一个表字段的sql语句
- python中列表数据汇总和平均值_python的列表List求均值和中位数实例
- 20万数据 sql 快还是 java快?_H2数据库学习(一)
- python有哪些方面_Python学习中最基本的内容,看看有哪些需要我们学习的
- java在线教程_如何自学java-已拿阿里25k offer
- docker和虚拟机的区别_详解win7操作系统下安装部署Docker环境
- html用bmob做留言,bmob js-sdk 在vue中的使用教程
- java 文件拷贝保留原来的属性,Java - 复制JPG,同时保留所有文件属性
- oracle的scn增量备份,【Oracle】基于SCN的增量备份修复DataGuard GAP