📜  使用信号量的生产者消费者问题 |设置 1(1)

📅  最后修改于: 2023-12-03 15:22:22.252000             🧑  作者: Mango

使用信号量的生产者消费者问题 |设置 1

介绍

本文将介绍如何使用信号量来解决生产者-消费者问题,并且设置缓冲区大小为1。生产者-消费者问题是一个经典的并发问题,生产者和消费者同时执行,生产者往缓冲区中放入数据,而消费者从缓冲区中取出数据。如果生产者向缓冲区中放入数据而缓冲区已满,生产者需要等待消费者从缓冲区中取走一个数据后,才能继续往缓冲区中放入数据;同样的,如果消费者从缓冲区中取出数据而缓冲区为空,消费者需要等待生产者往缓冲区中放入数据后,才能继续从缓冲区中取出数据。这个问题可以使用信号量来解决。

实现

我们需要定义三个信号量:一个用于表示缓冲区是否为空,一个用于表示缓冲区是否已满,一个用于互斥,防止多个线程同时对缓冲区进行操作。

#include <semaphore.h>
#include <pthread.h>

sem_t full;    //缓冲区是否已满
sem_t empty;   //缓冲区是否为空
sem_t mutex;   //互斥锁

初始化这三个信号量:

sem_init(&full, 0, 0);
sem_init(&empty, 0, 1);
sem_init(&mutex, 0, 1);

我们需要定义一个缓冲区,以及生产者和消费者线程,它们从缓冲区中取出和放入数据。

int buffer;   //缓冲区
pthread_t producer_tid, consumer_tid;

void *producer(void *arg) {
    int i;
    for (i = 0; i < 10; i++) {
        sem_wait(&empty);   //缓冲区是否为空
        sem_wait(&mutex);   //互斥锁
        buffer = i;
        sem_post(&mutex);   //互斥锁
        sem_post(&full);    //缓冲区是否已满
    }
    pthread_exit(NULL);
}

void *consumer(void *arg) {
    int i;
    for (i = 0; i < 10; i++) {
        sem_wait(&full);    //缓冲区是否已满
        sem_wait(&mutex);   //互斥锁
        int value = buffer;
        sem_post(&mutex);   //互斥锁
        sem_post(&empty);   //缓冲区是否为空
        printf("Consumed: %d\n", value);
    }
    pthread_exit(NULL);
}

在main函数中创建线程,并等待线程结束。

int main() {
    pthread_create(&producer_tid, NULL, producer, NULL);
    pthread_create(&consumer_tid, NULL, consumer, NULL);
    pthread_join(producer_tid, NULL);
    pthread_join(consumer_tid, NULL);
    return 0;
}

其中,sem_wait(&full)和sem_wait(&empty)会阻塞线程,等待信号量的值变成非零值。当信号量的值大于0时,它会将信号量的值减1。而sem_post(&full)和sem_post(&empty)会增加信号量的值。sem_wait(&mutex)和sem_post(&mutex)用于互斥,只有当互斥锁处于已解锁状态才能修改共享资源。

总结

在本文中,我们介绍了如何使用信号量来解决生产者-消费者问题,设置缓冲区大小为1。信号量是一种用于进程或线程间同步与通信的基本工具,使得程序能够安全地访问共享资源,避免了数据竞争的问题。