用C语言编程实现生产者-消费者问题的模拟
时间: 2023-05-29 15:01:30 浏览: 341
这里提供一个基于线程和信号量的生产者-消费者问题的模拟程序:
```
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE]; // 缓冲区
int in = 0; // 下一个生产者将把一个项目放到缓冲区的位置
int out = 0; // 下一个消费者将从缓冲区中移除一个项目的位置
sem_t empty; // 空的缓冲区的数量
sem_t full; // 满的缓冲区的数量
sem_t mutex; // 互斥锁
void* producer(void* arg) {
int* items = (int*) arg;
for (int i = 0; i < *items; i++) {
sem_wait(&empty);
sem_wait(&mutex);
buffer[in] = 1;
printf("Producer produced item %d.\n", in);
in = (in + 1) % BUFFER_SIZE;
sem_post(&mutex);
sem_post(&full);
}
pthread_exit(0);
}
void* consumer(void* arg) {
int* items = (int*) arg;
for (int i = 0; i < *items; i++) {
sem_wait(&full);
sem_wait(&mutex);
int item = buffer[out];
printf("Consumer consumed item %d.\n", out);
out = (out + 1) % BUFFER_SIZE;
sem_post(&mutex);
sem_post(&empty);
}
pthread_exit(0);
}
int main(int argc, char** argv) {
if (argc != 3) {
printf("Usage: %s <producer items> <consumer items>\n", argv[0]);
return 1;
}
int producer_items = atoi(argv[1]);
int consumer_items = atoi(argv[2]);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, producer, &producer_items);
pthread_create(&consumer_thread, NULL, consumer, &consumer_items);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
return 0;
}
```
这个程序中,有一个缓冲区数组 `buffer`,用于模拟实际生产者和消费者的共享缓冲区。缓冲区长度为 `BUFFER_SIZE`,因此可以放置 `BUFFER_SIZE` 个项目。
主线程从命令行参数中读取了生产者和消费者应该创建和消费的项目数量。在 `main` 函数中,我们初始化了三个信号量:
- `empty`:缓冲区中可用空位的数量,初始值为 `BUFFER_SIZE`;
- `full`:缓冲区中已经存储的项目的数量,初始值为 0;
- `mutex`:用于在生产者和消费者之间互斥地访问缓冲区的标记,初始值为 1。
我们在 `producer` 函数中模拟了生产者正常工作的逻辑。它首先等待信号量 `empty`,以检查是否有空位可用于存储下一个项目。这是一个有限制生产者的影响的措施。如果 `empty` 为 0,则表示缓冲区已满,因此生产者必须等待某个消费者消费一些项目,以便腾出空位。
如果 `empty` 大于零,则生产者已经得到了绿灯,可以执行它的工作了。对信号量 `mutex` 加锁以确保在生产者和消费者之间互斥地访问缓冲区的数据。生产者存储一个新项目之后,更新 `in` 值,以指向缓冲区中下一个可用的位置。最后,生产者释放信号量 `mutex` 和 `full`。如果此时有等待 `full` 的消费者,则它可以获得信号量,以通知缓冲区中有新项目可用。
与 `producer` 函数类似,我们在 `consumer` 函数中模拟了消费者的正常工作逻辑。首先等待信号量 `full`,以检查是否有项目可供消费。这是一个有限制消费者的影响的措施。如果 `full` 为 0,则表示缓冲区为空,因此消费者必须等待某个生产者生产一些项目,以便有项目可供消费。
如果 `full` 大于零,则消费者已经得到了绿灯,可以执行其工作了。对信号量 `mutex` 加锁以确保在生产者和消费者之间互斥地访问缓冲区的数据。消费者获取下一个项目,更新 `out` 值,以指向缓冲区中下一个可消费的项目。最后,消费者释放信号量 `mutex` 和 `empty`。如果此时有等待 `empty` 的生产者,则它可以获得信号量,以通知缓冲区中有空位可供使用。
最后,我们在主线程中创建生产者和消费者线程,并等待它们完成。在退出程序之前,我们销毁了三个信号量。
阅读全文
相关推荐
![c](https://img-home.csdnimg.cn/images/20250102104920.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![-](https://img-home.csdnimg.cn/images/20241231044833.png)
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![doc](https://img-home.csdnimg.cn/images/20241231044833.png)
![docx](https://img-home.csdnimg.cn/images/20241231044901.png)
![doc](https://img-home.csdnimg.cn/images/20241231044833.png)
![docx](https://img-home.csdnimg.cn/images/20241231044901.png)
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![-](https://img-home.csdnimg.cn/images/20241231044901.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![docx](https://img-home.csdnimg.cn/images/20241231044901.png)