Linux下多任务间通信和同步-条件变量
嵌入式开发交流群280352802,289195589,欢迎加入!
概述
互斥锁的一个明显缺点是它只有两种状态:锁定和非锁定.而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法解决了互斥锁的不足,它常此互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其他的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程.这些线程将重新锁定互斥锁并重新测试条件是否满足.条件变量的基本操作有以下两个:
- 触发条件:当条件变为true时;
- 等待条件:挂起线程直到其他线程触发条件.
条件变量采用的数据类型是pthread_cond_t,在使用之前必须要进行初始化,与互斥锁类型,也包括两种方式.
静态初始化:可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量;
动态初始化:在申请内存(malloc)后,通过pthread_cond_init进行初始化.注意在释放内存前需要调用pthread_cond_destory.
系统调用pthread_cond_init()
该调用将创建一个条件变量,其原型为:#include <pthread.h>
int pthread_cond_init(pthread_cond_t*restrict cond,pthread_condattr_t *restrict attr);
当pthread_cond_init的attr参数为NULL时,会创建一个默认属性的条件变量;非默认的条件变量需要设置条件变量属性,我们可以参考man手册.
系统调用pthread_cond_wait()
该系统调用对传递给pthread_cond_wait的互斥锁变量cond进行保护,其原型:int pthread_cond_wait(pthread_cond_t*restrict cond,pthread_mutex_t *restric mutex);
函数把调用线程放到等待条件的线程列表上,等待条件函数等待条件变为真,然后对互斥锁解锁,这两个操作是原子的.这样即使关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的事件通道,线程也不会错过条件的任何变化.当pthread_cond_wait返回时,互斥量将再次被锁住.
系统调用pthread_cond_timedwait()
该系统调用功能与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的值.
系统调用pthread_cond_signal()
该系统调用线程条件已经满足。其原型为:#include <pthread.h>
int pthread_cond_signal(pthread_cond_t*cond);
该系统调用通知线程条件已经满足。
系统调用pthread_cond_broadsignal()
该系统调用通知所有线程条件已经满足.其原型为:#include <pthread.h>
int pthread_cond_broadsignal(pthread_cond_t*cond);
与pthread_cond_signal()函数不同,该调用将通知等待该条件的所有线程.
系统调用pthread_cond_destroy()
该系统调用清楚动态分配的互斥锁变量。其原型为:#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;
}