cjozGV 的学生作业:
#include // printf, fprintf
#include // atoi, exit
#include // bool 类型
#include // POSIX 线程库
#include // usleep
static int number = 0; // 当前库存数量 (共享变量)
static int total_of_produce = 0; // 以生产总数
static int total_of_consume = 0; // 以消费总数
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *producer(void *arg){
int cnt = atoi((char *)arg); // 将命令行参数转为整数,表示生产数量
for (int i = 0; i < cnt; i++) {
pthread_mutex_lock(&mtx); // 加锁,进入临界区
number++; // 库存+1
total_of_produce++; // 总生产+1
printf("生产者 [%ld] 生产一个产品,产品总数=%d\n",pthread_self(),number);
pthread_cond_signal(&cond); // 通知消费者有货了
pthread_mutex_unlock(&mtx); // 解锁,退出临界区
usleep(100000); // 模拟生产耗时 100ms
}
return NULL;
}
void *consumer(void *arg){
(void)arg; // 忽略未使用的参数
while (1){
pthread_mutex_lock(&mtx);
// 如果库存为0且还有未消费的产品,就等待
while (number == 0 && total_of_consume < total_of_produce){
pthread_cond_wait(&cond,&mtx);
}
// 如果消费数已达到生产总数,且库存为0,退出循环
if (total_of_consume >= total_of_produce && number == 0){
pthread_mutex_unlock(&mtx);
break;
}
number--; // 消费一个产品
total_of_consume++; // 总消费+1
printf("消费者 [%ld] 消费一个产品,产品总数=%d\n",pthread_self(),number);
usleep(150000); // 模拟消费耗时 150ms
}
return NULL;
}
int main(int argc,char *argv[]){
if (argc < 2){
fprintf(stderr,"用法: %s num1 num2 ...\n",argv[0]);
exit(EXIT_FAILURE);
}
int n = argc - 1; // 生产者数量
pthread_t producers[n]; // 保存生产者线程id
pthread_t consumer_tid; // 消费者线程id
// 创建消费者线程
pthread_create(&consumer_tid,NULL,consumer,NULL);
// 创建多个生产者线程
for (int i = 0; i < n; i++) {
pthread_create(&producers[i],NULL,producers,argv[i+1]);
}
// 等待所有生产者线程结束
for (int i = 0; i < n; i++) {
pthread_join(producers[i],NULL);
}
// 等待所有消费者线程结束
for (int i = 0; i < n; i++) {
pthread_join(consumer_tid,NULL);
}
pthread_mutex_destroy(&mtx);
pthread_cond_destroy(&cond);
printf("所有产品生产=%d,消费=%d,程序结束\n",total_of_produce,total_of_consume);
return 0;
}