条件变量是利用线程间共享得全局变量进行同步的一种机制,主要包括两个动作:一个线程等待“条件变量的条件成立”而挂起;另一个线程使“条件成立”给出条件成立信号。为了防止竞争,条件变量得使用总是和一个互斥锁结合在一起。
1、创建和注销
条件变量和互斥锁一样,有两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER,动态方式使用pthread_coud_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)函数,cond_attr设置为NULL即可。注销需要使用int pthread_cond_destroy(pthread_cond_t *cond);
2、等待和激发
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
timewait方式表示超过时间条件没有满足则返回ETIMEOUT,结束等待 ,这个time是以绝对时间形式出现,即0表示格林尼治时间1970年1月1日0时0分0秒。为了防止多个线程同时请求pthread_cond_wait(),需要用互斥锁(mutex)来限定phread_cond_wait()的操作。对cond的操作必须是互斥的。下面是配合pthread_cleanup_push(),pthread_cleanup_pop()的一个示例程序:
#include "pthread.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct _Node
{
int number;
struct _Node *next;
};
typedef struct _Node Node;
Node *head;
/*信号量和条件变量*/
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/*线程异常时处理函数*/
static void cleanup_handler(void *arg)
{
printf("cleanup_handler\n");
free(arg);
(void)pthread_mutex_unlock(&mtx);
}
/*
pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop之前异常退出(return是正常退出,其他是异常),那么系统就会执行这个回调函数(回调函数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常退出,pthread_cleanup_pop就把对应的回调函数取消了
*/
static void* thread_func(void *arg)
{
Node *p = NULL;
printf("in thread_func()\n");
/*注册线程异常处理函数*/
pthread_cleanup_push(cleanup_handler, p);
while (1)
{
pthread_mutex_lock(&mtx);
while (NULL != head)
{
/*如果条件不满足,则挂起*/
pthread_cond_wait(&cond, &mtx);
p = head;
printf("Got %d from front of queue\n",p->number);
free(p);
pthread_mutex_unlock(&mtx);
}
}
/*清空线程异常处理函数*/
pthread_cleanup_pop(0);
return 0;
}
int main()
{
pthread_t tid;
int i;
Node *p;
pthread_create(&tid, NULL, thread_func, NULL);
for(i = 0; i < 10; i++)
{
printf("int main():%d", i);
p = (Node*)malloc(sizeof(Node));
p->number = i;
pthread_mutex_lock(&mtx);
p->next = head;
head = p;
/*通知条件OK了*/
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
sleep(1);
}
printf("thread 1 wanna end then cancel thread2.\n");
pthread_cancel(tid);
pthread_join(tid, NULL);
printf("All done\n");
return 0;
}
输出结果如下:
int main():0in thread_func()
int main():1Got 1 from front of queue
int main():2Got 2 from front of queue
int main():3Got 3 from front of queue
int main():4Got 4 from front of queue
int main():5Got 5 from front of queue
int main():6Got 6 from front of queue
int main():7Got 7 from front of queue
int main():8Got 8 from front of queue
int main():9Got 9 from front of queue
thread 1 wanna end then cancel thread2.
cleanup_handler
All done