生产者消费者问题及llinux系统下的实现

问题描述:假设在生产者与消费者之间有一个大小为n的缓冲区,生产者要向缓冲区里存放东西,消费者要从中取出东西,该如何控制二者能够不冲突的运转。

解决方法:当缓冲区满时生产者不可再放入,当缓冲区空时消费者不可再取出。

                  当有生产者向缓冲区存放东西时,其他生产者不可以再向缓冲区输出;当有消费者从缓冲区取出东西时,其他消费者不可以从缓冲区取出东西。

具体实现:1.通过两个信号量s1,s2来控制当前是生产者还是消费者占用缓冲区。

                   2.通过互斥锁,来决定具体为哪一个生产者向缓冲区生产东西。(消费者类似)

图示及解释:

首先,一个大小为n的缓冲区,分别定义两个信号量s1 = n,s2 = 0,如果s1为0则消费者不能从缓冲区中取出东西(s2为0类似)。这样我们对应的p、v操作就能确定

接着,当生产者执行p操作,所有的生产者线程都会抢占那个往缓冲区写入的机会,这时当有一个生产者线程抢到这个机会就立即上锁,防止别的线程打扰,写完、开锁、v操作、结束。

这里有一个需要注意的点:究竟是先p操作还是先上锁?

想想如果先上锁会怎样->假如生产者lock(上锁),这时只能紧接着执行p操作,然后要向缓冲区写入内容,但是如果缓冲区这时候是满的呢,就会无法写入,同时已经lock操作了,消费者也没机会从缓冲区取出东西,就会发生死锁!

理解以上内容代码即可实现:


//生产者消费者问题

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

#define BUFF_MAX 30   //缓冲区大小

pthread_mutex_t mutex; //保证互斥访问缓冲区
sem_t sem_empty;
sem_t sem_full;

int in = 0; //表示生产
int out = 0;

char buff[BUFF_MAX];

void* pro_fun(void* arg)
{
    for(int i = 0; i < 30; i++)
    {
        sem_wait(&sem_empty);                           //p(s1)
        pthread_mutex_lock(&mutex);                     //lock
        buff[in] = rand() % 100;                        //write
        printf("post:%d producer:%d\n", in, buff[in]);
        in = (in + 1) % BUFF_MAX;   //移动in指针
        pthread_mutex_unlock(&mutex);                   //unlock
        sem_post(&sem_full);                            //v(s2)
    }
}

void* con_fun(void* arg)
{
    for(int i = 0; i < 20; i++)
    {
        sem_wait(&sem_full);                              //p(s2)
        pthread_mutex_lock(&mutex);                       //lock
        printf("---post%d consumer:%d\n", out, buff[out]);//read
        out = (out + 1) % BUFF_MAX;                 


        pthread_mutex_unlock(&mutex);                      //unlock
        sem_post(&sem_empty);                              //v(s2)
    }
}

int main()
{
    sem_init(&sem_empty, 0, BUFF_MAX);
    sem_init(&sem_full, 0, 0);
    pthread_mutex_init(&mutex, NULL);
    
    pthread_t pro_id[2];
    for(int i = 0; i < 2; i++) 
    {
        pthread_create(&pro_id[i], NULL, pro_fun, NULL);//启动两个生产者
    }
    
    pthread_t con_id[3];
    for(int i = 0; i <3; i++)
    {
        pthread_create(&con_id[i], NULL, con_fun, NULL);//启动三个消费者
    }   

    for(int i = 0; i < 2; i++)
    {
        pthread_join(pro_id[i], NULL);
    }

    for(int i = 0; i < 3; i++)
    {
        pthread_join(con_id[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    sem_destroy(&sem_empty);
    sem_destroy(&sem_full);


    exit(0);
}

运行结果:

 一点理解:生产者与消费者并不是什么从属关系,不是生产然后消费,生产然后消费。

而是当有机会去生产或者有机会去消费的时候,就会抓紧机会去做该做的事,这其实是与线程的并发性有关,各个线程会去争抢资源,而我们要做的就是处理好这种竞争关系,避免陷入死锁这种情况。

其实人生也是不必太过于执着某个东西,一切自有天意,正确的人或事都会在正确的时间来到你身边,撞过南墙,就别再执着于南墙了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值