【操作系统】c语言--使用信号量解决生产者和消费者问题

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
🔥c++系列专栏:C/C++零基础到精通 🔥

给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ

在这里插入图片描述

c语言内容💖:

专栏:c语言之路重点知识整合

【c语言】全部知识点总结


信号量

信号量是一种同步机制,可用于保护共享资源,控制进程的访问以及协调进程之间的通信。

在生产者和消费者问题中,可以使用两个信号量:一个用于生产者,另一个用于消费者。

假设缓冲区的大小为N,生产者信号量的初始值为N,消费者信号量的初始值为0。

接下来,生产者和消费者可以使用P操作和V操作来访问缓冲区。

P操作(等待信号量):如果信号量的值为0,则进程将阻塞,直到信号量的值变为正数。如果信号量的值大于0,则进程将减少信号量的计数器并继续执行。

V操作(释放信号量):如果有进程在等待信号量,则唤醒其中一个进程。否则,信号量的计数器将增加,以表示一个资源已经可用。

分析

创建两个线程,一个用于生产者,另一个用于消费者。它们共享一个大小为5的环形缓冲区。

当生产者线程生成一个新项目时,它使用blank_number信号量将空闲空间的数量减少1,然后使用互斥变量mutex1添加到环形缓冲区中。生产者使用product_number信号量将队列项目的数量增加1。

当消费者线程消费一个项目时,它使用product_number信号量将队列项目的数量减少1,然后使用互斥变量mutex1从环形缓冲区中删除。消费者使用blank_number信号量将空余的空间数量增加1。

这种基于信号量的方法可以保证生产者和消费者之间的同步性。

  • 如果缓存区已满,则生产者线程将在blank_number信号量处阻塞,并等待直至有可用的空间。

  • 如果缓存区为空,则消费者线程将在product_number信号量处阻塞。

代码

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>

#define NUM 5

int queue[NUM];                                     //全局数组实现环形队列
sem_t blank_number, product_number, mutex1;                 //空格子信号量, 产品信号量

void *producer(void *arg)
{
    int i = 0;

    while (1) {
        sem_wait(&blank_number);                    //生产者将空格子数--,为0则阻塞等待
        sem_wait(&mutex1);
        queue[i] = rand() % 1000 + 1;               //生产一个产品
        printf("----Produce---%d\n", queue[i]);
        sem_post(&mutex1);
        sem_post(&product_number);                  //将产品数++

        i = (i+1) % NUM;                            //借助下标实现环形
        sleep(rand()%3);
    }
}

void *consumer(void *arg)
{
    int i = 0;

    while (1) {
        sem_wait(&product_number);                  //消费者将产品数--,为0则阻塞等待
        sem_wait(&mutex1);
        printf("-Consume---%d\n", queue[i]);
        queue[i] = 0;                               //消费一个产品
        sem_post(&mutex1);
        sem_post(&blank_number);                    //消费掉以后,将空格子数++

        i = (i+1) % NUM;
        sleep(rand()%3);
    }
}

int main(int argc, char *argv[])
{
    pthread_t pid, cid;

    sem_init(&blank_number, 0, NUM);                //初始化空格子信号量为5
    sem_init(&product_number, 0, 0);                //产品数为0
    sem_init(&mutex1, 0, 1);

    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);

    pthread_join(pid, NULL);
    pthread_join(cid, NULL);

    sem_destroy(&blank_number);
    sem_destroy(&product_number);

    return 0;
}

运行结果

在这里插入图片描述


在这里插入图片描述

大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●)
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
生产者-消费者问题是一个经典的并发问题,在多线程编程中经常用到。在该问题中,有两种角色:生产者消费者生产者生成数据,并且将数据放入共享的缓冲区中;而消费者则从该缓冲区中取出数据并进行处理。但是由于生产者消费者是并发执行的,在多线程环境下,可能会出现一些问题,如竞争条件、死锁等。因此,需要采用一些同步机制来保证正确的执行顺序。 在实验七中,我们将使用信息量来解决生产者-消费者问题。信息量是一种同步机制,它通过一个计数器来实现线程间的同步和协调。当计数器的值为0时,表示缓冲区为空,消费者等待;当计数器的值为缓冲区的容量时,表示缓冲区已满,生产者等待。当生产者向缓冲区中添加一个数据时,计数器的值加1;当消费者从缓冲区中取出一个数据时,计数器的值减1。 下面是使用信息量解决生产者-消费者问题的代码示例(C语言): ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 5 // 缓冲区大小 int buffer[BUFFER_SIZE]; // 缓冲区 int in = 0; // 生产者放置数据的位置 int out = 0; // 消费者取数据的位置 sem_t empty_sem; // 空信号量 sem_t full_sem; // 满信号量 pthread_mutex_t mutex; // 互斥锁 void *producer(void *arg) // 生产者线程函数 { int i; for (i = 0; i < 10; i++) { sem_wait(&empty_sem); // 等待空信号量 pthread_mutex_lock(&mutex); // 加锁 // 往缓冲区放入数据 buffer[in] = i; printf("producer put %d in buffer[%d]\n", i, in); in = (in + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); // 解锁 sem_post(&full_sem); // 发送满信号量 sleep(1); // 生产者睡眠1秒 } } void *consumer(void *arg) // 消费者线程函数 { int i, data; for (i = 0; i < 10; i++) { sem_wait(&full_sem); // 等待满信号量 pthread_mutex_lock(&mutex); // 加锁 // 从缓冲区取出数据 data = buffer[out]; printf("consumer get %d from buffer[%d]\n", data, out); out = (out + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); // 解锁 sem_post(&empty_sem); // 发送空信号量 sleep(2); // 消费者睡眠2秒 } } int main(int argc, char *argv[]) { pthread_t tid1, tid2; sem_init(&empty_sem, 0, BUFFER_SIZE); // 初始化空信号量 sem_init(&full_sem, 0, 0); // 初始化满信号量 pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 pthread_create(&tid1, NULL, producer, NULL); // 创建生产者线程 pthread_create(&tid2, NULL, consumer, NULL); // 创建消费者线程 pthread_join(tid1, NULL); // 等待生产者线程 pthread_join(tid2, NULL); // 等待消费者线程 sem_destroy(&empty_sem); // 销毁空信号量 sem_destroy(&full_sem); // 销毁满信号量 pthread_mutex_destroy(&mutex); // 销毁互斥锁 return 0; } ``` 在该示例中,信号量empty_sem表示缓冲区空的数量,full_sem表示缓冲区满的数量。生产者线程在向缓冲区中添加一个数据时,需要等待empty_sem信号量,如果缓冲区已满,则阻塞等待;添加完数据后,需要发送full_sem信号量,表示缓冲区中已经有了一个数据。消费者线程在从缓冲区中取出一个数据时,需要等待full_sem信号量,如果缓冲区为空,则阻塞等待;取出数据后,需要发送empty_sem信号量,表示缓冲区中空的数量又加1。互斥锁mutex用于保护缓冲区的访问,避免竞争条件的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天喜Studio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值