模型采取Linux/UNIX系统编程手册
这个模型很好,也把概念讲清楚了,加了中文注释
生产者
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
avail++; /*这是一个原子操作 */
s = pthread_mutex_unlock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_unlock");
s = pthread_cond_signal(&cond); /* 唤醒消费者 */
if (s != 0)
errExitEN(s, "pthread_cond_signal");
消费者
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
while (avail == 0)
{
s = pthread_cond_wait(&cond, &mtx);
if (s != 0)
errExitEN(s, "pthread_cond_wait");
}
完整代码
#include <time.h>
#include <pthread.h>
#include "tlpi_hdr.h"
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;
static void *
threadFunc(void *arg)
{
int cnt = atoi((char *) arg);
int s, j;
for (j = 0; j < cnt; j++) {
sleep(1);
/* Code to produce a unit omitted */
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
avail++; /* Let consumer know another unit is available */
s = pthread_mutex_unlock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_unlock");
s = pthread_cond_signal(&cond); /* Wake sleeping consumer */
if (s != 0)
errExitEN(s, "pthread_cond_signal");
}
return NULL;
}
int
main(int argc, char *argv[])
{
pthread_t tid;
int s, j;
int totRequired; /* Total number of units that all threads
will produce */
int numConsumed; /* Total units so far consumed */
Boolean done;
time_t t;
t = time(NULL);
/* Create all threads */
totRequired = 0;
for (j = 1; j < argc; j++) {
totRequired += atoi(argv[j]);
s = pthread_create(&tid, NULL, threadFunc, argv[j]);
if (s != 0)
errExitEN(s, "pthread_create");
}
/* Loop to consume available units */
numConsumed = 0;
done = FALSE;
for (;;) {
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
while (avail == 0) { /* Wait for something to consume */
s = pthread_cond_wait(&cond, &mtx);
if (s != 0)
errExitEN(s, "pthread_cond_wait");
}
/* At this point, 'mtx' is locked... */
while (avail > 0) { /* Consume all available units */
/* Do something with produced unit */
numConsumed ++;
avail--;
printf("T=%ld: numConsumed=%d\n", (long) (time(NULL) - t),
numConsumed);
done = numConsumed >= totRequired;
}
s = pthread_mutex_unlock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_unlock");
if (done)
break;
/* Perhaps do other work here that does not require mutex lock */
}
exit(EXIT_SUCCESS);
}