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

 

时间: 2024-09-21 16:42:30

linux C++ 多线程使用pthread_cond 条件变量的相关文章

POSIX多线程编程:条件变量pthread_cond_t

条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程.这些线程将重新锁定互斥锁并重新测试条件是否满足.一般说来,条件变量被用来进行线承间的同步. 1.条件变量的结构为pthread_cond_t (相当于windows中的事件的作用) 2.条件变量的初始化 int

练习生产者与消费者-PYTHON多线程中的条件变量同步-Queue

以前练习过,但好久不用,手生,概念也生了, 重温一下.. URL: http://www.cnblogs.com/holbrook/tag/%E5%A4%9A%E7%BA%BF%E7%A8%8B/ ~~~~~~~ 互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法.线程首先acquire一个条件变量,然后判断一些条件

Linux下互斥量与条件变量详解

1. 首先pthread_cond_wait 的定义是这样的 The pthread_cond_wait() and pthread_cond_timedwait() functions are used to block on a condition variable. They are called with mutex locked by the calling thread or undefined behaviour will result. These functions atomi

Linux 的多线程编程的高效开发经验

  简介:          本文中我们针对 Linux 上多线程编程的主要特性总结出 5 条经验,用以改善 Linux 多线程编程的习惯和避免其中的开发陷阱.在本文中,我们穿插一些 Windows 的编程用例用以对比 Linux 特性,以加深读者印象.   背景:    Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们从 5 个方面总结出 Li

二、(LINUX 线程同步) 互斥量、条件变量以及生产者消费者问题

原创转载请注明出处: 接上一篇: 一.(LINUX 线程同步) 引入  http://blog.itpub.net/7728585/viewspace-2137980/ 在线程同步中我们经常会使用到mutex互斥量,其作用用于保护一块临界区,避免多线程并发操作对这片临界区带来的数据混乱, POSIX的互斥量是一种建议锁,因为如果不使用互斥量也可以访问共享数据,但是可能是不安全的. 其原语包含: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

Linux线程管理必备:解析互斥量与条件变量的详解_C 语言

   做过稍微大一点项目的人都知道,力求程序的稳定性和调度的方便,使用了大量的线程,几乎每个模块都有一个专门的线程处理函数.而互斥量与条件变量在线程管理中必不可少,任务间的调度几乎都是由互斥量与条件变量控制.互斥量的实现与进程中的信号量(无名信号量)是类似的,当然,信号量也可以用于线程,区别在于初始化的时候,其本质都是P/V操作.编译时,记得加上-lpthread或-lrt哦.    有关进程间通信(消息队列)见:进程间通信之深入消息队列的详解 一.互斥量 1. 初始化与销毁:    对于静态分

Linux线程同步之条件变量

条件变量是线程可用的另一种同步机制.条件变量给多个线程提供了一个会合的场所.条件本身是由互斥量保护的.线程在改变 条件状态前必须首先锁住互斥量. 条件变量的初始化 pthread_cond_init 去除初始化 pthread_cond_destroy 等待 pthread_cond_wait 满足条件给向进程发送信号 pthread_cond_signal 下面程序展示了利用条件变量等待另外两个线程满足条件时,第三个进程继续向前执行 #include <stdio.h> #include &

并发编程(二):分析Boost对 互斥量和条件变量的封装及实现生产者消费者问题

请阅读上篇文章<并发编程实战: POSIX 使用互斥量和条件变量实现生产者/消费者问题>.当然不阅读亦不影响本篇文章的阅读. Boost的互斥量,条件变量做了很好的封装,因此比"原生的"POSIX mutex,condition variables好用.然后我们会通过分析boost相关源码看一下boost linux是如何对pthread_mutex_t和pthread_cond_t进行的封装. 首先看一下condition_variable_any的具体实现,代码路径:/

Linux的多线程编程的高效开发经验

简介:本文中我们针对 Linux 上多线程编程的主要特性总结出 5 条经验, 用以改善 Linux 多线程编程的习惯和避免其中的开发陷阱.在本文中,我们穿 插一些 Windows 的编程用例用以对比 Linux 特性,以加深读者印象. 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会 导致程序问题不穷,死锁不断.本文中我们从 5 个方面总结出 Linux 多线程编 程上的问题,