系统中有多个生产者和消费者,共享一个可以存放1000个产品的缓冲区,当缓冲区未满时,生产者可以放入一件产品,缓冲区不空时,消费者可以从缓冲区取产品,否则等待。要求消费者从缓冲区连续取走10件产品后,其他消费者才可以再取产品。试用信号量(或/和锁)机制描述生产者和消费者之间的同步关系。
时间: 2024-03-03 18:50:08 浏览: 190
信号量机制应用经典实例-生产者、消费者
可以使用两个信号量来实现生产者和消费者之间的同步关系,一个信号量用于表示缓冲区中可用的产品数量,另一个信号量用于表示缓冲区中已经被消费者取走但还未计数的产品数量。
具体实现方式如下:
```c++
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1000
#define CONSUMER_BATCH_SIZE 10
#define NUM_CONSUMERS 5
#define NUM_PRODUCERS 5
sem_t mutex; // 互斥信号量
sem_t full; // 缓冲区有可用产品的信号量
sem_t empty; // 缓冲区有空位的信号量
int buffer[BUFFER_SIZE]; // 缓冲区
int num_items_consumed = 0; // 已经被消费者取走但还未计数的产品数量
void *producer(void *arg) {
int item;
while (1) {
// 生产一个新产品
item = rand();
// 等待缓冲区有空位
sem_wait(&empty);
// 互斥地将产品放入缓冲区
sem_wait(&mutex);
buffer[(int)arg] = item;
sem_post(&mutex);
// 通知缓冲区有可用产品
sem_post(&full);
}
}
void *consumer(void *arg) {
int item;
int count = 0;
while (1) {
// 等待缓冲区有可用产品
sem_wait(&full);
// 互斥地从缓冲区取出一个产品
sem_wait(&mutex);
item = buffer[(int)arg];
sem_post(&mutex);
// 更新计数器,并判断是否需要等待
count++;
if (count == CONSUMER_BATCH_SIZE) {
num_items_consumed += CONSUMER_BATCH_SIZE;
count = 0;
if (num_items_consumed == BUFFER_SIZE) {
num_items_consumed = 0;
sem_post(&empty);
}
}
// 通知缓冲区有空位
sem_post(&empty);
// 处理产品
printf("Consumer %d consumed item %d\n", (int)arg, item);
}
}
int main() {
sem_init(&mutex, 0, 1);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_t producers[NUM_PRODUCERS];
pthread_t consumers[NUM_CONSUMERS];
int i;
// 创建生产者线程
for (i = 0; i < NUM_PRODUCERS; i++) {
pthread_create(&producers[i], NULL, producer, (void*)i);
}
// 创建消费者线程
for (i = 0; i < NUM_CONSUMERS; i++) {
pthread_create(&consumers[i], NULL, consumer, (void*)i);
}
// 等待所有线程结束
for (i = 0; i < NUM_PRODUCERS; i++) {
pthread_join(producers[i], NULL);
}
for (i = 0; i < NUM_CONSUMERS; i++) {
pthread_join(consumers[i], NULL);
}
sem_destroy(&mutex);
sem_destroy(&full);
sem_destroy(&empty);
return 0;
}
```
在上述代码中,生产者线程通过等待空位信号量empty来等待缓冲区有空位,然后通过互斥信号量mutex将产品放入缓冲区,并通过信号量full通知缓冲区有可用产品。消费者线程则通过等待可用产品信号量full来等待缓冲区有可用产品,然后通过互斥信号量mutex从缓冲区中取出一个产品,并更新计数器。当一个消费者取走10件产品时,它会将计数器清零,并通过信号量empty通知其他消费者可以继续取产品。
阅读全文