Linux下多任务间通信和同步-条件变量
互斥锁的一个明显缺点是它只有两种状态:锁定和非锁定.而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法解决了互斥锁的不足,它常此互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程.这些线程将重新锁定互斥锁并重新测试条件是否满足.条件变量的基本操作有以下两个:
#include <pthread.h> int pthread_cond_init(pthread_cond_t*restrict cond,pthread_condattr_t *restrict attr);当pthread_cond_init的attr参数为NULL时,会创建一个默认属性的条件变量;非默认的条件变量需要设置条件变量属性,我们可以参考man手册.
int pthread_cond_wait(pthread_cond_t*restrict cond,pthread_mutex_t *restric mutex);函数把调用线程放到等待条件的线程列表上,等待条件函数等待条件变为真,然后对互斥锁解锁,这两个操作是原子的.这样即使关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的事件通道,线程也不会错过条件的任何变化.当pthread_cond_wait返回时,互斥量将再次被锁住.
#include <pthread.h> int pthread_cond_t timedwait(pthread_cond_t*restrict cond, pthread-mutex_t *restrict mutex, conststruct timespec *restrict timeout);timeout值指定了等待的事件。其数据结构structtimespec如下所示:
struct timespec{ time_t tv_sev; /*seconds*/ long tvnsec; /*nanoseconds*/ };等待的事件值以s或ns计算,注意这是一个绝对值而不是相对值,需要将当前的事件加上需要等待的事件才是timeout的值.
#include <pthread.h> int pthread_cond_signal(pthread_cond_t*cond);该系统调用通知线程条件已经满足。
#include <pthread.h> int pthread_cond_broadsignal(pthread_cond_t*cond);与pthread_cond_signal()函数不同,该调用将通知等待该条件的所有线程.
#include <pthread.h> int pthread_cond_destroy(pthread_cond_t*cond);
条件变量的应用实例
/**************************************************************************************/ /*简介:互斥锁和条件变量同步线程演示程序 */ /*************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> pthread_mutex_t count_lock; pthread_cond_t count_ready; int count; void *decrement_count(void *arg) { pthread_mutex_lock(&count_lock); printf("decrement:waiting\n"); /*等待满足条件,期间互斥量仍然可用*/ while (count == 0) pthread_cond_wait(&count_ready, &count_lock); count = count - 1; printf("decrement:count = %d\n", count); pthread_mutex_unlock(&count_lock); pthread_exit(NULL); } void *increment_count(void *arg) { pthread_mutex_lock(&count_lock); printf("increment:running\n"); count = count + 1; /*通知线程条件已满足*/ pthread_cond_signal(&count_ready); printf("increment:count = %d\n", count); pthread_mutex_unlock(&count_lock); pthread_exit(NULL); } int main() { pthread_t tid1,tid2; count=0; pthread_mutex_init(&count_lock, NULL); pthread_cond_init(&count_ready, NULL); pthread_create(&tid1, NULL, decrement_count, NULL); sleep(1); pthread_create(&tid2, NULL, increment_count, NULL); /*等待decrement退出*/ pthread_join(tid2, NULL); printf("decrement quit\n"); pthread_join(tid1, NULL); return 0; }