生产者消费者问题(信号量) 参考教材中的生产者消费者算法,创建5个进程,其中两个进程为生产者进程,3个进程为消费者进程。一个生产者进程试图不断地在一个缓冲中写入大写字母,另一个生产者进程试图不断地在缓冲中写入小写字母。3个消费者不断地从缓冲中读取一个字符并输出。为了使得程序的输出易于看到结果,仿照的实例程序,分别在生产者和消费者进程的合适的位置加入一些随机睡眠时间。 可选的实验:在上面实验的基础上实现部分消费者有选择地消费某些产品。例如一个消费者只消费小写字符,一个消费者只消费大写字母,而另一个消费者则无选择地消费任何产品。消费者要消费的产品没有时,消费者进程被阻塞。注意缓冲的管理。给出具体的c语音代码 并且给出具体的可以在VM虚拟机linux的gcc编译与操作代码
时间: 2024-03-18 15:45:32 浏览: 52
以下是使用信号量实现的生产者消费者问题的代码,其中包括了部分消费者有选择地消费某些产品的实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define BUFFER_SIZE 10 // 缓冲区大小
#define PRODUCER_NUM 2 // 生产者数量
#define CONSUMER_NUM 3 // 消费者数量
char buffer[BUFFER_SIZE]; // 缓冲区
int in = 0; // 生产者写入位置
int out = 0; // 消费者读取位置
sem_t empty; // 空闲缓冲区数量的信号量
sem_t full; // 已占用缓冲区数量的信号量
sem_t mutex; // 互斥信号量,用于访问缓冲区的同步
void *producer(void *arg) {
int id = *(int *)arg;
while (1) {
sleep(rand() % 3); // 随机睡眠时间
char c;
if (id == 0) {
c = 'A' + rand() % 26; // 大写字母
} else {
c = 'a' + rand() % 26; // 小写字母
}
sem_wait(&empty); // 等待空闲缓冲区
sem_wait(&mutex); // 互斥访问缓冲区
buffer[in] = c;
in = (in + 1) % BUFFER_SIZE; // 更新写入位置
printf("Producer %d produces %c\n", id, c);
sem_post(&mutex); // 释放互斥信号量
sem_post(&full); // 增加已占用缓冲区数量
}
}
void *consumer(void *arg) {
int id = *(int *)arg;
while (1) {
char c;
if (id == 0) {
sem_wait(&full); // 消费小写字母时需要等待有小写字母可消费
sem_wait(&mutex); // 互斥访问缓冲区
for (int i = 0; i < BUFFER_SIZE; i++) {
if (buffer[i] >= 'a' && buffer[i] <= 'z') {
c = buffer[i];
buffer[i] = ' '; // 消费后清空位置
break;
}
}
} else if (id == 1) {
sem_wait(&full); // 消费大写字母时需要等待有大写字母可消费
sem_wait(&mutex); // 互斥访问缓冲区
for (int i = 0; i < BUFFER_SIZE; i++) {
if (buffer[i] >= 'A' && buffer[i] <= 'Z') {
c = buffer[i];
buffer[i] = ' '; // 消费后清空位置
break;
}
}
} else {
sem_wait(&full); // 消费任何字符时只需要等待有字符可消费
sem_wait(&mutex); // 互斥访问缓冲区
c = buffer[out];
buffer[out] = ' '; // 消费后清空位置
out = (out + 1) % BUFFER_SIZE; // 更新读取位置
}
printf("Consumer %d consumes %c\n", id, c);
sem_post(&mutex); // 释放互斥信号量
sem_post(&empty); // 增加空闲缓冲区数量
}
}
int main() {
// 初始化信号量
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);
// 创建线程
pthread_t producers[PRODUCER_NUM], consumers[CONSUMER_NUM];
int producer_ids[PRODUCER_NUM], consumer_ids[CONSUMER_NUM];
for (int i = 0; i < PRODUCER_NUM; i++) {
producer_ids[i] = i;
pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
}
for (int i = 0; i < CONSUMER_NUM; i++) {
consumer_ids[i] = i;
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(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
return 0;
}
```
在Linux下使用gcc编译并运行该代码的方法如下:
1. 打开终端并进入代码所在目录
2. 输入以下命令进行编译:
```
gcc -o main main.c -pthread
```
3. 输入以下命令运行程序:
```
./main
```
阅读全文