外观
csapp/sync_demo.c
配套源码,运行方法见同目录 README。返回实验总览。
c
/* A one-slot channel: condition variables guard predicates, not event counts. */
#include <assert.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define ITEMS 10000
typedef struct {
pthread_mutex_t lock;
pthread_cond_t readable, writable;
bool full;
int item;
long total;
} Channel;
static void checked(int result) { if (result != 0) { fprintf(stderr, "pthread error %d\n", result); abort(); } }
static void *producer(void *argument) {
Channel *c = argument;
for (int i = 1; i <= ITEMS; ++i) {
checked(pthread_mutex_lock(&c->lock));
while (c->full) checked(pthread_cond_wait(&c->writable, &c->lock));
c->item = i;
c->full = true;
checked(pthread_cond_signal(&c->readable));
checked(pthread_mutex_unlock(&c->lock));
}
return NULL;
}
static void *consumer(void *argument) {
Channel *c = argument;
for (int i = 1; i <= ITEMS; ++i) {
checked(pthread_mutex_lock(&c->lock));
while (!c->full) checked(pthread_cond_wait(&c->readable, &c->lock));
assert(c->item == i);
c->total += c->item;
c->full = false;
checked(pthread_cond_signal(&c->writable));
checked(pthread_mutex_unlock(&c->lock));
}
return NULL;
}
int main(void) {
Channel channel = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,
PTHREAD_COND_INITIALIZER, false, 0, 0};
pthread_t p, c;
checked(pthread_create(&p, NULL, producer, &channel));
checked(pthread_create(&c, NULL, consumer, &channel));
checked(pthread_join(p, NULL));
checked(pthread_join(c, NULL));
assert(channel.total == (long)ITEMS * (ITEMS + 1) / 2);
printf("sync: items=%d sum=%ld\n", ITEMS, channel.total);
checked(pthread_mutex_destroy(&channel.lock));
checked(pthread_cond_destroy(&channel.readable));
checked(pthread_cond_destroy(&channel.writable));
return 0;
}