利用记录型信号量解决生产者消费者问题完整代码
时间: 2023-11-06 14:05:39 浏览: 174
下面是一个利用记录型信号量解决生产者消费者问题的完整代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 5 // 缓冲区大小
#define PRODUCER_NUM 2 // 生产者个数
#define CONSUMER_NUM 2 // 消费者个数
#define ITEM_NUM 10 // 生产的产品总数
int buffer[BUFFER_SIZE]; // 缓冲区
int in = 0; // 当前可插入位置
int out = 0; // 当前可消费位置
sem_t mutex; // 互斥信号量,用于保护缓冲区
sem_t full; // 计数信号量,表示缓冲区中可用的产品数
sem_t empty; // 计数信号量,表示缓冲区中空槽的数目
void *producer(void *arg) {
int id = *(int *)arg;
int item;
for (int i = 0; i < ITEM_NUM; i++) {
item = rand() % 100 + 1; // 随机生成一个产品
sem_wait(&empty); // 等待空槽
sem_wait(&mutex); // 保护缓冲区
buffer[in] = item; // 将产品放入缓冲区
printf("Producer %d produced item %d.\n", id, item);
in = (in + 1) % BUFFER_SIZE; // 更新插入位置
sem_post(&mutex); // 释放缓冲区
sem_post(&full); // 增加可用产品数
}
pthread_exit(NULL);
}
void *consumer(void *arg) {
int id = *(int *)arg;
int item;
for (int i = 0; i < ITEM_NUM; i++) {
sem_wait(&full); // 等待可用产品
sem_wait(&mutex); // 保护缓冲区
item = buffer[out]; // 从缓冲区取出一个产品
printf("Consumer %d consumed item %d.\n", id, item);
out = (out + 1) % BUFFER_SIZE; // 更新消费位置
sem_post(&mutex); // 释放缓冲区
sem_post(&empty); // 增加空槽数
}
pthread_exit(NULL);
}
int main() {
pthread_t producers[PRODUCER_NUM];
pthread_t consumers[CONSUMER_NUM];
int producer_ids[PRODUCER_NUM];
int consumer_ids[CONSUMER_NUM];
sem_init(&mutex, 0, 1); // 初始化互斥信号量
sem_init(&full, 0, 0); // 初始化计数信号量
sem_init(&empty, 0, BUFFER_SIZE); // 初始化计数信号量
// 创建生产者线程
for (int i = 0; i < PRODUCER_NUM; i++) {
producer_ids[i] = i + 1;
pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
}
// 创建消费者线程
for (int i = 0; i < CONSUMER_NUM; i++) {
consumer_ids[i] = i + 1;
pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]);
}
// 等待生产者线程结束
for (int i = 0; i < PRODUCER_NUM; i++) {
pthread_join(producers[i], NULL);
}
// 等待消费者线程结束
for (int i = 0; i < CONSUMER_NUM; i++) {
pthread_join(consumers[i], NULL);
}
sem_destroy(&mutex); // 销毁互斥信号量
sem_destroy(&full); // 销毁计数信号量
sem_destroy(&empty); // 销毁计数信号量
return 0;
}
```
在该代码中,我们使用了三个信号量:互斥信号量 `mutex`、计数信号量 `full` 和 `empty`。其中,`mutex` 用于保护缓冲区,`full` 和 `empty` 分别表示缓冲区中可用的产品数和空槽的数目。
在生产者线程中,每次生成一个产品后,我们先等待 `empty` 信号量,表示缓冲区中有空槽,然后等待 `mutex` 信号量,保护缓冲区,将产品放入缓冲区,更新插入位置,最后释放 `mutex` 信号量和增加 `full` 信号量,表示可用产品数增加了一个。
在消费者线程中,每次取出一个产品后,我们先等待 `full` 信号量,表示缓冲区中有可用的产品,然后等待 `mutex` 信号量,保护缓冲区,从缓冲区中取出一个产品,更新消费位置,最后释放 `mutex` 信号量和增加 `empty` 信号量,表示空槽数增加了一个。
在 `main` 函数中,我们先初始化三个信号量,然后创建生产者和消费者线程,最后等待线程结束,销毁信号量。
注意,在实际开发中,我们应该使用 `pthread_mutex_t` 和 `pthread_cond_t` 来实现互斥和条件变量,这样会更加灵活和高效。
阅读全文