互斥锁用于上锁,条件变量用于等待
#include <pthread.h> int pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr); int pthread_cond_signal(pthread_cond_t *cptr); // return 0 / errno每个条件变量总是有一个互斥锁与之关联,等待某个信号之前需获取mutex,等待某个条件时,会释放该mutex,然后线程睡眠;条件满足时,线程会从睡眠中醒来再次获取该互斥锁,继续运行...最后释放该互斥锁。pthread_cond_signal函数唤醒等待该条件线程中的某个线程。
// 互斥锁和条件变量实现生产者消费者 /* include globals */ #include "unpipc.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 }; /* end globals */ void *produce(void *), *consume(void *); /* include main */ int main(int argc, char **argv) { int i, nthreads, count[MAXNTHREADS]; pthread_t tid_produce[MAXNTHREADS], tid_consume; if (argc != 3) err_quit("usage: prodcons6 <#items> <#threads>"); nitems = min(atoi(argv[1]), MAXNITEMS); nthreads = min(atoi(argv[2]), MAXNTHREADS); Set_concurrency(nthreads + 1); /* 4create all producers and one consumer */ 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); } /* end main */ /* include prodcons */ 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); } /* end prodcons */
int pthread_cond_broadcast(pthread_cond_t *cptr); int pthread_cond_timedwait(pthread_cond_t *cptr, pthread_mutex_t *mptr, const struct timespec *abstime); // return 0/errno