- 实验目的
实现线程同步
- 实验内容
3个生产者,2个消费者,库存大小为10
生产者共享一个变量产品编号productID,每生产一个产品,productID加1,不能出现重复编号。每个生产者每生产一个产品,打印出生产者的进程/线程标识符信息,以及生产的产品编号信息;生产者生产一个产品后,休眠2ms消费者每消费一个产品,打印出消费者的进程/线程标识符信息,以及消费的产品编号信息; 消费者消费一个产品后,休眠3ms
- 实验过程
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <unistd.h>
- #define BUFFER_SIZE 10
- #define NUM_PRODUCERS 3
- #define NUM_CONSUMERS 2
- //库存
- int buffer[BUFFER_SIZE];
- //生产/消费库存的第几个空位
- int bufID = 1;
- //生产、消费的产品号
- int productID = 1, consumeID = 1;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- int p_ID = 2;//第几号生产者
- int c_ID = 1;//第几号消费者
- void *producer(void *arg) {
- while (1) {
- usleep(2000); // 休眠2ms
- p_ID = (p_ID+1)%3;
- pthread_mutex_lock(&mutex);//互斥信号量
- if (bufID <= BUFFER_SIZE) {//仓库还有空位
- int index = bufID - 1;//数组从0开始
- buffer[index] = bufID;
- printf("Producer %d productID %d produced product %d\n", p_ID, productID, buffer[index]);
- productID++;//下一个生产的产品号
- bufID++;//下一个库存空位号
- }
- pthread_mutex_unlock(&mutex);//释放信号量
- }
- return NULL;
- }
- void *consumer(void *arg) {
- while (1) {
- usleep(3000); // 休眠3ms
- c_ID = (c_ID+1)%2;
- pthread_mutex_lock(&mutex);
- if (bufID > 1) {
- int index = bufID - 2;//1.数组从0开始 2.生产者加了1,但没生产减回来
- printf("Consumer %d productID %d consumed product %d\n", c_ID, consumeID, buffer[index]-1);
- bufID--;//库存下一个空位
- consumeID++;//消费第几号产品
- }
- pthread_mutex_unlock(&mutex);
- }
- return NULL;
- }
- int main() {
- pthread_t producer_threads[NUM_PRODUCERS];
- pthread_t consumer_threads[NUM_CONSUMERS];
- // 创建生产者线程
- for (int i = 0; i < NUM_PRODUCERS; i++) {
- pthread_create(&producer_threads[i], NULL, producer, NULL);
- }
- // 创建消费者线程
- for (int i = 0; i < NUM_CONSUMERS; i++) {
- pthread_create(&consumer_threads[i], NULL, consumer, NULL);
- }
- // 等待线程结束
- for (int i = 0; i < NUM_PRODUCERS; i++) {
- pthread_join(producer_threads[i], NULL);
- }
- for (int i = 0; i < NUM_CONSUMERS; i++) {
- pthread_join(consumer_threads[i], NULL);
- }
- return 0;
- }
结果:
四、实验结论(心得)
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个被消费了)