linux下实现信号量机制模拟实现生产者-消费者问题
时间: 2023-06-14 10:06:04 浏览: 279
在Linux下,可以使用系统提供的信号量机制来实现生产者-消费者问题。下面是一个简单的示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_BUFFER_SIZE 10 // 缓冲区最大容量
#define PRODUCER_NUM 2 // 生产者数量
#define CONSUMER_NUM 2 // 消费者数量
int buffer[MAX_BUFFER_SIZE]; // 缓冲区
int buffer_index = 0; // 缓冲区中剩余元素个数
pthread_mutex_t mutex; // 互斥锁
sem_t full; // 缓冲区满的信号量
sem_t empty; // 缓冲区空的信号量
void *producer(void *arg) {
int item, i;
while (1) {
item = rand() % 100; // 生产一个随机数
sem_wait(&empty); // 等待缓冲区空的信号量
pthread_mutex_lock(&mutex); // 加锁
if (buffer_index < MAX_BUFFER_SIZE) {
buffer[buffer_index++] = item; // 将元素放入缓冲区
printf("Producer %d produced item %d\n", *((int *) arg), item);
}
pthread_mutex_unlock(&mutex); // 解锁
sem_post(&full); // 发送缓冲区满的信号量
sleep(rand() % 3);
}
return NULL;
}
void *consumer(void *arg) {
int item, i;
while (1) {
sem_wait(&full); // 等待缓冲区满的信号量
pthread_mutex_lock(&mutex); // 加锁
if (buffer_index > 0) {
item = buffer[--buffer_index]; // 从缓冲区取出一个元素
printf("Consumer %d consumed item %d\n", *((int *) arg), item);
}
pthread_mutex_unlock(&mutex); // 解锁
sem_post(&empty); // 发送缓冲区空的信号量
sleep(rand() % 3);
}
return NULL;
}
int main() {
int i, producer_id[PRODUCER_NUM], consumer_id[CONSUMER_NUM];
pthread_t producer_thread[PRODUCER_NUM], consumer_thread[CONSUMER_NUM];
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
sem_init(&empty, 0, MAX_BUFFER_SIZE); // 初始化缓冲区空的信号量
sem_init(&full, 0, 0); // 初始化缓冲区满的信号量
// 创建生产者线程
for (i = 0; i < PRODUCER_NUM; i++) {
producer_id[i] = i + 1;
pthread_create(&producer_thread[i], NULL, producer, (void *) &producer_id[i]);
}
// 创建消费者线程
for (i = 0; i < CONSUMER_NUM; i++) {
consumer_id[i] = i + 1;
pthread_create(&consumer_thread[i], NULL, consumer, (void *) &consumer_id[i]);
}
// 等待生产者线程结束
for (i = 0; i < PRODUCER_NUM; i++) {
pthread_join(producer_thread[i], NULL);
}
// 等待消费者线程结束
for (i = 0; i < CONSUMER_NUM; i++) {
pthread_join(consumer_thread[i], NULL);
}
pthread_mutex_destroy(&mutex); // 销毁互斥锁
sem_destroy(&empty); // 销毁缓冲区空的信号量
sem_destroy(&full); // 销毁缓冲区满的信号量
return 0;
}
```
在这个例子中,我们使用了一个互斥锁和两个信号量来实现生产者-消费者问题。其中,互斥锁用于保护缓冲区的数据结构,防止多个线程同时对其进行修改。缓冲区空的信号量用于通知生产者线程可以继续向缓冲区中添加元素,缓冲区满的信号量用于通知消费者线程可以从缓冲区中取出元素。
在生产者线程中,我们先使用 `sem_wait()` 函数等待缓冲区空的信号量。一旦信号量被发送,就说明缓冲区中有空位可以存放新的元素了。然后我们使用互斥锁保护缓冲区的数据结构,检查缓冲区是否已满。如果缓冲区未满,就将元素放入缓冲区,并输出一条生产者线程的信息。最后再使用 `sem_post()` 函数发送缓冲区满的信号量,通知消费者线程可以从缓冲区中取出元素了。
在消费者线程中,我们先使用 `sem_wait()` 函数等待缓冲区满的信号量。一旦信号量被发送,就说明缓冲区中有元素可以取出了。然后我们使用互斥锁保护缓冲区的数据结构,检查缓冲区是否为空。如果缓冲区非空,就从缓冲区中取出一个元素,并输出一条消费者线程的信息。最后再使用 `sem_post()` 函数发送缓冲区空的信号量,通知生产者线程可以继续向缓冲区中添加元素了。
最后,在主函数中,我们创建了若干个生产者线程和消费者线程,并等待它们结束。在每个线程中,我们使用 `rand()` 函数随机生成一个元素,并将其放入或取出缓冲区。同时,我们使用 `sleep()` 函数模拟不同的线程执行速度,以便更好地观察程序的执行过程。
阅读全文