实现线程同步

本文描述了一个实验,通过C语言和多线程实现3个生产者和2个消费者共享资源的问题,使用互斥信号量mutex确保线程同步,避免并发时数据冲突。实验中详细展示了如何控制生产者和消费者的行为,以及修正产品编号计数的问题。
摘要由CSDN通过智能技术生成
  • 实验目的

实现线程同步

  • 实验内容

3个生产者,2个消费者,库存大小为10

生产者共享一个变量产品编号productID,每生产一个产品,productID加1,不能出现重复编号。每个生产者每生产一个产品,打印出生产者的进程/线程标识符信息,以及生产的产品编号信息;生产者生产一个产品后,休眠2ms消费者每消费一个产品,打印出消费者的进程/线程标识符信息,以及消费的产品编号信息; 消费者消费一个产品后,休眠3ms

  • 实验过程
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <pthread.h>  
  4. #include <unistd.h>  
  5.   
  6. #define BUFFER_SIZE 10  
  7. #define NUM_PRODUCERS 3  
  8. #define NUM_CONSUMERS 2  
  9.   
  10. //库存  
  11. int buffer[BUFFER_SIZE];  
  12. //生产/消费库存的第几个空位  
  13. int bufID = 1;  
  14. //生产、消费的产品号  
  15. int productID = 1, consumeID = 1;  
  16. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  17.   
  18. int p_ID = 2;//第几号生产者  
  19. int c_ID = 1;//第几号消费者  
  20. void *producer(void *arg) {  
  21.     while (1) {  
  22.         usleep(2000);  // 休眠2ms  
  23.     p_ID = (p_ID+1)%3;  
  24.         pthread_mutex_lock(&mutex);//互斥信号量  
  25.   
  26.         if (bufID <= BUFFER_SIZE) {//仓库还有空位  
  27.             int index = bufID - 1;//数组从0开始  
  28.             buffer[index] = bufID;  
  29.             printf("Producer %d productID %d produced product %d\n", p_ID, productID, buffer[index]);  
  30.             productID++;//下一个生产的产品号  
  31.             bufID++;//下一个库存空位号  
  32.         }  
  33.         pthread_mutex_unlock(&mutex);//释放信号量  
  34.     }  
  35.   
  36.     return NULL;  
  37. }  
  38.   
  39. void *consumer(void *arg) {  
  40.     while (1) {  
  41.         usleep(3000);  // 休眠3ms  
  42.     c_ID = (c_ID+1)%2;  
  43.         pthread_mutex_lock(&mutex);  
  44.   
  45.         if (bufID > 1) {  
  46.             int index = bufID - 2;//1.数组从0开始 2.生产者加了1,但没生产减回来  
  47.             printf("Consumer %d productID %d consumed product %d\n", c_ID, consumeID, buffer[index]-1);  
  48.             bufID--;//库存下一个空位  
  49.             consumeID++;//消费第几号产品  
  50.         }  
  51.   
  52.         pthread_mutex_unlock(&mutex);  
  53.     }  
  54.   
  55.     return NULL;  
  56. }  
  57.   
  58. int main() {  
  59.     pthread_t producer_threads[NUM_PRODUCERS];  
  60.     pthread_t consumer_threads[NUM_CONSUMERS];  
  61.   
  62.     // 创建生产者线程  
  63.     for (int i = 0; i < NUM_PRODUCERS; i++) {  
  64.         pthread_create(&producer_threads[i], NULL, producer, NULL);  
  65.     }  
  66.   
  67.     // 创建消费者线程  
  68.     for (int i = 0; i < NUM_CONSUMERS; i++) {  
  69.         pthread_create(&consumer_threads[i], NULL, consumer, NULL);  
  70.     }  
  71.   
  72.     // 等待线程结束  
  73.     for (int i = 0; i < NUM_PRODUCERS; i++) {  
  74.         pthread_join(producer_threads[i], NULL);  
  75.     }  
  76.   
  77.     for (int i = 0; i < NUM_CONSUMERS; i++) {  
  78.         pthread_join(consumer_threads[i], NULL);  
  79.     }  
  80.   
  81.     return 0;  
  82. }  

结果:

四、实验结论(心得)

1.生产者消费者问题即通过mutex信号量控制不能两个生产者一起生产,或两个消费者一起消费,同时每生产消费一次,库存就要作出对应的修改。

2.由于本题要求输出生产/消费者编号,所以我使用了p_ID,c_ID两个全局变量,并各自取模来代表每次执行任务的是哪一个生产者消费者。

3.由于题目要求输出生产消费的货品的编号,我一开始只设置了一个product_ID,每生产一个就+1,并用一个全局变量old_product来保存product_ID,没消费一个就-1。但是后来发现了这种做法的弊端,即每次消费只会从当前生产的最新产品开始消费,比如生产了货物1 2 3,消费了3 2,然后又生产了4 5 6,下次消费会从6 开始消费,而不是消费1。为解决这一问题,我又设置了另一个全局变量consume_ID来代表消费货物编号,同样的从1开始计数。

4.数组buf[index]代表的是生产/消费了仓库的第index空位的货品,需要输出已经占了多少空位,消费行为要输出buf[index]-1(因为第index个被消费了)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值