操作系统生产者消费者问题
时间: 2024-05-10 20:16:40 浏览: 103
生产者消费者问题是一个经典的同步问题,它涉及到两类进程:生产者和消费者,它们共享一个缓冲区。生产者进程从输入源获取数据并将其放入缓冲区中,而消费者进程从缓冲区中取出数据并进行处理。该问题的目标是确保生产者和消费者进程之间的正确同步,以防止数据竞争和死锁。
以下是一个简单的C语言实现,使用了信号量来实现同步:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
#define MAX_ITEMS 100
int buffer[BUFFER_SIZE]; // 缓冲区
int in = 0; // 缓冲区插入位置
int out = 0; // 缓冲区取出位置
sem_t empty; // 记录缓冲区空闲位置的信号量
sem_t full; // 记录缓冲区已有数据的信号量
pthread_mutex_t mutex; // 互斥锁,保证缓冲区插入和取出操作的原子性
void *producer(void *arg)
{
int item;
for (int i = 0; i < MAX_ITEMS; i++) {
item = rand() % 1000;
sem_wait(&empty); // 等待缓冲区有空闲位置
pthread_mutex_lock(&mutex); // 获取互斥锁
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
printf("Producer produced item %d\n", item);
pthread_mutex_unlock(&mutex); // 释放互斥锁
sem_post(&full); // 发送缓冲区已有数据的信号
}
pthread_exit(NULL);
}
void *consumer(void *arg)
{
int item;
for (int i = 0; i < MAX_ITEMS; i++) {
sem_wait(&full); // 等待缓冲区有数据
pthread_mutex_lock(&mutex); // 获取互斥锁
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
printf("Consumer consumed item %d\n", item);
pthread_mutex_unlock(&mutex); // 释放互斥锁
sem_post(&empty); // 发送缓冲区空闲的信号
}
pthread_exit(NULL);
}
int main()
{
pthread_t producer_thread, consumer_thread;
sem_init(&empty, 0, BUFFER_SIZE); // 初始化空闲位置信号量为 BUFFER_SIZE
sem_init(&full, 0, 0); // 初始化已有数据信号量为 0
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
return 0;
}
```
在这个例子中,我们使用了两个信号量 empty 和 full 来分别记录缓冲区的空闲位置和已有数据。当生产者进程往缓冲区中插入数据时,它会等待 empty 信号量,当缓冲区有空闲位置时才能继续插入数据,并且插入操作需要获取互斥锁以保证原子性。当生产者插入数据后,它会发送 full 信号量来通知消费者有数据可用。
当消费者进程从缓冲区中取出数据时,它会等待 full 信号量,当缓冲区有数据时才能继续取出数据,并且取出操作需要获取互斥锁以保证原子性。当消费者取出数据后,它会发送 empty 信号量来通知生产者有空闲位置可用。
通过这种方式,我们可以确保生产者和消费者进程之间的正确同步,避免了数据竞争和死锁的问题。
阅读全文