相互排斥锁用于上锁,条件变量则用于等待。条件变量是类型为pthread_cond_t的变量。一般使用例如以下函数:
#include <pthread.h> int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr); int pthread_cond_signal(pthread_cond_t *cptr);每一个条件变量总是有一个相互排斥锁与之关联。调用pthread_cond_wait等待某个条件为真时,还会指定其条件变量的地址和所关联的相互排斥锁的地址。
使用条件变量的生产者-消费者程序例如以下:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define MAXNITEMS 1000000 #define MAXNTHREADS 100 /*globals shared by threads*/ int nitems; /*read-only by producer and consumer*/ int buff[MAXNITEMS]; struct{ pthread_mutex_t mutex; int nput; /*next index to store*/ int nval; /*next value to store*/ }put = { PTHREAD_MUTEX_INITIALIZER }; struct{ pthread_mutex_t mutex; pthread_cond_t cond; int nready; /*number ready for consumer*/ }nready={ PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER }; int min(int a, int b) { return (a < b) ? (a) : (b); } void *produce(void *), *consume(void *); int main(int argc, char **argv) { int i, nthreads, count[MAXNTHREADS]; pthread_t tid_produce[MAXNTHREADS], tid_consume; if(argc != 3){ printf("usage:produces6 <#items> <#threads>.\n"); return -1; } nitems = min(atoi(argv[1]), MAXNITEMS); nthreads = min(atoi(argv[2]), MAXNTHREADS); /*create all producers and one consumer*/ pthread_setconcurrency(nthreads + 1); for(i = 0; i < nthreads; i++){ count[i] = 0; pthread_create(&tid_produce[i], NULL, produce, &count[i]); } pthread_create(&tid_consume, NULL, consume, NULL); /*wait for all producers and the consumer*/ for(i = 0; i < nthreads; i++){ pthread_join(tid_produce[i], NULL); printf("count[%d] = %d\n", i, count[i]); } pthread_join(tid_consume, NULL); exit(0); } void * produce(void *arg) { for(;;){ pthread_mutex_lock(&put.mutex); if(put.nput >= nitems){ pthread_mutex_unlock(&put.mutex); return (NULL); /*array is full, we're done*/ } buff[put.nput] = put.nval; put.nput++; put.nval++; pthread_mutex_unlock(&put.mutex); pthread_mutex_lock(&nready.mutex); if(nready.nready == 0){ pthread_cond_signal(&nready.cond); } nready.nready++; pthread_mutex_unlock(&nready.mutex); *((int *)arg) += 1; } } void * consume(void *arg) { int i; for(i = 0; i < nitems; i++){ pthread_mutex_lock(&nready.mutex); while(nready.nready == 0) pthread_cond_wait(&nready.cond, &nready.mutex); nready.nready--; pthread_mutex_unlock(&nready.mutex); if(buff[i] != i) printf("buff[%d] = %d\n", i, buff[i]); } return(NULL); }