C语言多线程之生产者消费者问题

代码的关键部分是设置一个互斥量来模仿只有一个线程访问缓冲区。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

//设计缓冲区
#define N 4//缓冲区大小
int buf[N] = {0};//缓冲区初始化为0,表示一开始没有产品
int putin = 0;//数据入区位置
int takeout = 0;//数据出区位置

//设计信号量(信号量的大小可为>1的数)
sem_t unoccupied;//空位个数时
sem_t occupied;//产品各数

//设置互斥量(互斥量的大小为0或1)
pthread_mutex_t mutex; //表示一个缓冲区,模拟操作系统只有一个线程对缓冲区访问,不能同时有多个线程访问缓冲区

//设计时延函数(2层循环)
void delay (int len) {
	int i = rand () % len;
	int x;
	while (i > 0) {
		x = rand () % len;
		while (x > 0) {
			x--;
		}
		i--;	
	}
}

//设计可唤醒消费者的生产者
void producer() {
	while (1) {
		//模拟正在生产
		int d = 1 + rand () % 100;//代表生产的产品名字
		delay(50000);
		//生产后产品入库
		sem_wait(&unoccupied);//P操作,将对应的信号量unoccupied减1再与0进行比较大小,入库前判断是否有空位,有空位(比较结果>=0)则后续代码才能执行,否则阻塞当前进程
		//开始业务操作
		pthread_mutex_lock(&mutex); //加锁,当一个线程在访问缓冲区时,另一个线程来访问时被阻塞
		buf[putin] = d;
		printf("Put %d to the buffer at %d.\n",buf[putin],putin);
		putin++;
		if(putin == N) {//生产出的产品的投放顺序在缓冲区依序排放,即使前一个生产出的产品被消耗了,也是依序往后放
			putin = 0;//putin变为3以后自增为4的时将其置0
		}
		sem_post(&occupied);//V操作,可取物品信号量加1,唤醒
		pthread_mutex_unlock(&mutex); //当前线程访问完缓冲区以后解锁
	}
}

void consumer() {
	while (1) {
	//模拟正在取物品
	delay(5000);
	//进行消费 
	sem_wait(&occupied);//P操作,将对应的信号量occupied减1再与0进行比较大小,消费前判断是否有产品,有产品(比较结果>=0)则后续代码才能执行,否则阻塞当前进程
	pthread_mutex_lock(&mutex); 
	printf("Take out %d from the buffer at %d.\n",buf[takeout],takeout);
	buf[takeout] = -1; 
	takeout++;
	if (takeout == N) {
		takeout = 0;
	}
	sem_post(&unoccupied);//V操作,可生产空位信号量加1
	pthread_mutex_unlock(&mutex); 
	}
}

int main () {
	srand(time(NULL));

	//声明厂家消费者线程
	pthread_t manufacturer;
	pthread_t customer;

	//初始化信号量
	sem_init(&unoccupied, 0, N);
	sem_init(&occupied, 0, 0);

	//初始化互斥量
	pthread_mutex_init(&mutex, NULL); 

	//创建线程
	pthread_create(&manufacturer, NULL, (void *)producer, NULL);
	pthread_create(&customer, NULL, (void *)consumer, NULL);

	//阻塞当前线程,直到t1和t2线程执行结束
	pthread_join(manufacturer, NULL);
	pthread_join(customer, NULL);

	//撤销信号量
	sem_destroy(&unoccupied);
	sem_destroy(&occupied);
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_39656575/article/details/80720809