博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Linux 通过信号量semaphore实现生产者消费者模型

Posted on 2023-01-24 10:09  steve.z  阅读(93)  评论(0编辑  收藏  举报
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>


#define N 5

void sys_err(const char *msg) {
}


// 定义一个队列, 全局数组实现环形队列
int queue[N];

// 定义产品信号量 和 空格子信号量
sem_t sem_product, sem_blank;


// 生产者
void * producer(void *arg) {
	int i = 0;
	while(1) {
		// 阻塞等待有可用的 blank
		sem_wait(&sem_blank);
		// 随机产生一个产品
		queue[i] = rand() % 1000 + 1;
		// 打印输出产生的产品
		printf("-----produce: %d \n", queue[i]);
		// 产品已产生, 可以释放一个 product. 可以理解为sem_product++
		sem_post(&sem_product);
		// 设置 i 循环
		i = (i + 1) % N;
		sleep(rand() % 1);

	}
	// return NULL;
}

// 消费者
void * consumer(void *arg) {
	int i = 0;
	while(1) {
		// 消费者调用 sem_wait() 对产品阻塞
		sem_wait(&sem_product);
		// 打印获取到的产品
		printf("----------------------consumer: %d \n", queue[i]);
		// 将该位置的产品设置为 0, 表示该位置已经空出来了
		queue[i] = 0;
		// 成功拿走一个 product, 则释放出了一个 blank
		sem_post(&sem_blank);

		// 让 i 从 0 到 4 循环往复
		i = (i + 1) % N;

		sleep(rand() % 3);
	}
	// return NULL;
}

/* 生产者需要的是 blank, 当blank 都被填满的时候就阻塞了 */
/* 消费者需要的是 product, 当没有 product 的时候(即5个都是 blank)时,就阻塞了 */

/* 当消费者拿走一个 product 后,就空出了一个 blank, 所以可以释放一个 blank
   同理,当生产者产生一个 product 后,就多个一个产品, 所以可以释放一个 product
 */



int main(int argc, const char * argv[]) {
	pthread_t pid, cid;

	// 初始化 sem_blank 信号量为 5, 且为线程间共享
	sem_init(&sem_blank, 0, N);
	// 初始化 sem_product 信号量为0 , 且为线程间共享
	sem_init(&sem_product, 0, 0);

	// 创建生产者和消费者两个子线程
	pthread_create(&pid, NULL, producer, NULL);
	pthread_create(&cid, NULL, consumer, NULL);

	// 回收两个子线程
	pthread_join(pid, NULL);
	pthread_join(cid, NULL);

	// 回收两个信号量
	sem_destroy(&sem_blank);
	sem_destroy(&sem_product);

	return 0;
}