相互排斥锁用于上锁,条件变量则用于等待。条件变量是类型为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);
}