根据下面的实验要求(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符; (2)生产者和消费者各有两个以上; (3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码; (4)有界缓冲区设有20个存储单元,写入/取出的数据项设定为1-20这20个整型数;用信号量机制解决生产者消费者问题
时间: 2024-01-24 11:17:15 浏览: 71
以下是一个使用信号量机制解决生产者消费者问题的示例代码,其中使用了两个信号量:一个用于限制缓冲区中可写入的数量,一个用于限制缓冲区中可读取的数量。
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 20
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 2
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
sem_t empty, full;
pthread_mutex_t mutex;
void *producer(void *arg) {
int id = *(int*)arg;
int produced = 0;
while (1) {
int item = rand() % 20 + 1;
sem_wait(&empty);
pthread_mutex_lock(&mutex);
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
produced++;
printf("Producer %d produced item %d\n", id, item);
printf("Current buffer: ");
for (int i = 0; i < BUFFER_SIZE; i++) {
printf("%d ", buffer[i]);
}
printf("\n");
pthread_mutex_unlock(&mutex);
sem_post(&full);
if (produced == 10) {
break;
}
}
printf("Producer %d finished\n", id);
pthread_exit(NULL);
}
void *consumer(void *arg) {
int id = *(int*)arg;
int consumed = 0;
while (1) {
sem_wait(&full);
pthread_mutex_lock(&mutex);
int item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
consumed++;
printf("Consumer %d consumed item %d\n", id, item);
printf("Current buffer: ");
for (int i = 0; i < BUFFER_SIZE; i++) {
printf("%d ", buffer[i]);
}
printf("\n");
pthread_mutex_unlock(&mutex);
sem_post(&empty);
if (consumed == 10) {
break;
}
}
printf("Consumer %d finished\n", id);
pthread_exit(NULL);
}
int main() {
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
pthread_mutex_init(&mutex, NULL);
pthread_t producers[NUM_PRODUCERS];
pthread_t consumers[NUM_CONSUMERS];
int producer_ids[NUM_PRODUCERS];
int consumer_ids[NUM_CONSUMERS];
for (int i = 0; i < NUM_PRODUCERS; i++) {
producer_ids[i] = i + 1;
pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
consumer_ids[i] = i + 1;
pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]);
}
for (int i = 0; i < NUM_PRODUCERS; i++) {
pthread_join(producers[i], NULL);
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
pthread_join(consumers[i], NULL);
}
pthread_mutex_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}
```
在这个示例中,有两个生产者和两个消费者,每个生产者和消费者都有一个唯一的标识符。缓冲区大小为20,数据项为1到20之间的整数。生产者生成10个随机数据项并将它们放入缓冲区中,消费者从缓冲区中读取10个数据项并打印它们。在每个操作之后,程序会打印出当前缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
在主函数中,我们初始化了两个信号量(empty和full)和一个互斥锁(mutex)。然后创建了两个生产者和两个消费者线程,并等待它们完成。最后销毁了信号量和互斥锁。
当一个生产者线程想要放入一个数据项时,首先需要等待empty信号量,以确保缓冲区中还有空间可写入。然后获取互斥锁,将数据项放入缓冲区并更新in指针。打印出当前缓冲区的全部内容、当前指针位置和生产者线程的标识符。释放互斥锁并增加full信号量,表示缓冲区中有一个新的数据项可读取。
当一个消费者线程想要读取一个数据项时,首先需要等待full信号量,以确保缓冲区中有数据可读取。然后获取互斥锁,从缓冲区中读取数据项并更新out指针。打印出当前缓冲区的全部内容、当前指针位置和消费者线程的标识符。释放互斥锁并增加empty信号量,表示缓冲区中有一个新的空位可写入。
通过使用信号量和互斥锁,我们可以避免生产者和消费者同时访问缓冲区,从而保证了线程安全。
阅读全文