条件变量的if与while


此文是linux c++的一个程序,该程序要求是给定一个缓冲区,一个生产者,一个消费者,然后要求使用条件变量,互斥量来解决读写问题,其中有个重要的知识点就是,使用信号量的时候,如何保证线程安全,如果有一个生产者,多个消费者,这种情况下,条件变量wait地方就应该使用while,而非if,如果是单生产单消费,则可以用if。具体解释见代码注释

/* ex7-4.c */
#include <stdio.h>
#include <pthread.h>
#define BUFFER_SIZE 4
#define OVER (-1)
struct producers
{
    int buffer[BUFFER_SIZE];
    pthread_mutex_t lock;
    int readpos, writepos;
    pthread_cond_t notempty;
    pthread_cond_t notfull;
};


void init(struct producers *b)
{
    pthread_mutex_init(&b->lock,NULL);
    pthread_cond_init(&b->notempty,NULL);
    pthread_cond_init(&b->notfull,NULL);
    b->readpos=0;
    b->writepos=0;
}


void put(struct producers *b, int data)
{
    pthread_mutex_lock(&b->lock);
    while((b->writepos+1)%BUFFER_SIZE==b->readpos)
    {
        pthread_cond_wait(&b->notfull,&b->lock);
    }


    b->buffer[b->writepos]=data;
    b->writepos++;
    if(b->writepos>=BUFFER_SIZE) b->writepos=0;
    pthread_cond_signal(&b->notempty);
    pthread_mutex_unlock(&b->lock);
}


int get(struct producers *b)
{
    int data;
    pthread_mutex_lock(&b->lock);
    while(b->writepos==b->readpos)
    {  
       //此处为何是一个while 而不是if,假设现在一个生产者写了一个单位,而且广播给两个消费者,这时候,两个消费者wait都被返回,都被唤醒,假如第一个消费者率先拿到,这时候writepos==readpos,下面该第二个消费者去拿,这时候就会越过writepos访问,导致问题,所以这里,第二个消费者在wait被唤醒后,会继续执行while判断writepos和readpos,发现这两个还是保持相等状态,则第二个消费者就要继续wait
        pthread_cond_wait(&b->notempty,&b->lock);
    }
    data=b->buffer[b->readpos];
    b->readpos++;
    if(b->readpos>=BUFFER_SIZE) b->readpos=0;
    pthread_cond_signal(&b->notfull);
    pthread_mutex_unlock(&b->lock);
    return data;
}


struct producers  buffer;

void *producer(void *data)
{
    int n;
    for(n=0;n<10;n++)
    {
    printf("Producer : %d-->\n",n);
    put(&buffer,n);
    }
    put(&buffer,OVER);
    return NULL;
}


void *consumer(void *data)
{
    int d;
    while(1)
    {
    d=get(&buffer);
    if(d==OVER) break;
    printf("Consumer: --> %d\n",d);
    }
    return NULL;
}


int main()
{
    pthread_t tha,thb;
    void *retval;
    init(&buffer);
    pthread_create(&tha,NULL,producer,0);
    pthread_create(&thb,NULL,consumer,0);
    pthread_join(tha,&retval);
    pthread_join(thb,&retval);
    return 0;


}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值