一组生产者进程向一组消费者进程提供产品,两类进程共享一个由 n 个缓冲区组成的有界缓冲池,生产者进程向空缓冲池中投放产品,消费者进程从放有数据的缓冲池中取得产品并消费掉。只要缓冲池未满,生产者进程就可以把产品送入缓冲池;只要缓冲池未空,消费者进程便可以从缓冲池中取走产品。但禁止生产者进程向满的缓冲池再输送产品,也禁止消费者进程从空的缓冲池中提取产品。为了防止对缓冲池重复操作,故规定在任何时候,只有一个主体可以访问缓冲池。
void *consumer_func(void *arg) { intptr_t id = (intptr_t)arg; // 取出线程编号 for (int i = 0; i < CONSUME_TIMES; i++) { int data; sleep(1); sem_wait(&product_sem); pthread_mutex_lock(&mutex);
// 消费者从缓冲池读取数据 data = pool[head]; head = (head + 1) % POOL_SIZE; printf("Consumer %" PRIdPTR " read from pool!\r\n", id); printf("Pool size is %d.\r\n", (rear - head + POOL_SIZE) % POOL_SIZE); pthread_mutex_unlock(&mutex); sem_post(&pool_sem); } returnNULL; }
intmain() { int i; pthread_t producer_id[PRODUCER_NUM]; pthread_t consumer_id[CONSUMER_NUM]; pthread_mutex_init(&mutex, NULL);
int ret = sem_init(&pool_sem, 0, POOL_SIZE - 1); if (ret != 0) { printf("Failed to init pool_sem.\r\n"); exit(0); }
ret = sem_init(&product_sem, 0, 0); if (ret != 0) { printf("Failed to init product_sem.\r\n"); exit(0); }
for (i = 0; i < PRODUCER_NUM; i++) { // 创建生产者线程 ret = pthread_create(&producer_id[i], NULL, producer_func, (void *)(intptr_t)i); if (ret != 0) { printf("Create producer thread error.\r\n"); exit(0); }
void *philosopher_work(void *arg) { int id = *(int *)arg; printf("The philosopher[%d] has sat down.\r\n", id);
while (1) { thinking(id); take_forks(id); eating(id); put_down_forks(id); }
returnNULL; }
intmain() { int ret; int id[PHIL_NUM]; pthread_t phil_tid[PHIL_NUM];
// 初始化互斥锁和信号量 pthread_mutex_init(&phil_mutex, NULL); for (int i = 0; i < PHIL_NUM; i++) { if (sem_init(&phil_sem[i], 0, 0) != 0) { printf("Failed to init semaphore[%d].\r\n", i); return-1; } phil_state[i] = PHIL_THINK; }
// 创建哲学家线程 for (int i = 0; i < PHIL_NUM; ++i) { id[i] = i; ret = pthread_create(&phil_tid[i], NULL, philosopher_work, (void *)(&id[i])); if (ret != 0) { printf("Failed to create process for philosopher[%d].\r\n", i); return-1; } }
// 等待子线程 for (int i = 0; i < PHIL_NUM; i++) { pthread_join(phil_tid[i], NULL); }
// 回收资源 pthread_mutex_destroy(&phil_mutex); for (int i = 0; i < PHIL_NUM; i++) { sem_destroy(&phil_sem[i]); }
int ret = sem_init(&bucket_sem, 0, BUCKET_NUM); if (ret != 0) { printf("Failed to init bucket_sem.\r\n"); exit(0); }
ret = sem_init(&empty_sem, 0, TANK_SIZE); if (ret != 0) { printf("Failed to init empty_sem.\r\n"); exit(0); }
ret = sem_init(&full_sem, 0, 0); if (ret != 0) { printf("Failed to init full_sem.\r\n"); exit(0); }
for (i = 0; i < LITTLE_MONK_NUM; i++) { // 创建小和尚线程 ret = pthread_create(&little_monk_id[i], NULL, little_monk_func, (void *)(intptr_t)i); if (ret != 0) { printf("Create little monk thread error.\r\n"); exit(0); }
// 创建大和尚线程 ret = pthread_create(&big_monk_id[i], NULL, big_monk_func, (void *)(intptr_t)i); if (ret != 0) { printf("Create big monk thread error.\r\n"); exit(0); } }
for (i = 0; i < LITTLE_MONK_NUM; i++) { pthread_join(little_monk_id[i], NULL); pthread_join(big_monk_id[i], NULL); }