生产者和消费者模型的实现

相关函数

#include <pthread.h>  /*头文件*/
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);   /*初始化一个互斥锁*/
int pthread_mutex_destroy(pthread_mutex_t *mutex);/*注销一个互斥锁*/
int pthread_mutex_lock(pthread_mutex_t *mutex);  /*加锁,不成功,阻塞等待*/
int pthread_mutex_unlock(pthread_mutex_t *mutex);/*解锁*/
int pthread_join(pthread_t th,void *thread_return); /*等待线程结束*/
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);/*初始化条件变量*/
pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex); /*基于条件变量阻塞,无条件等待*/
pthread_cond_signal(pthread_cond_t *cond); /*解除特定线程阻塞,存在多个线程按入队顺序激活激活其中一个*/
pthread_cond_destory(pthread_cond_t *cond); /*清除条件变量*/

模型分析

  • 生产者产生数据并放入缓冲区,缓冲区满,生产者阻塞。
  • 消费者提取缓冲区中的数据,缓冲区空,消费者阻塞。
  • 缓冲区未满且不空,生产者与消费者处于一种动态平衡的过程。
    这里写图片描述

伪代码

  • 根据模型分析,两个线程同时指向了相同的缓冲区域,为了保护数据的完整性,所以必须使用互斥锁。
/*生产者*/
put_info(...)
{
        加锁保护数据;
        while(缓冲区已满)
        生产者等待;
        生产者开始生产数据;
        解锁数据;
        给消费者发送信号;        
}
/*消费者*/
get_info(...)
{
        加锁保护数据;
        while(缓冲区为空)
        消费者等待;
        消费者开始提取数据;
        解锁数据;
        给生产者发送信号;        
}

实现过程

基本结构

#define BUFFER_SIZR 4                              //规定缓冲区大小
#define OVER -1                                    //定义结束标志
typedef struct producers{                               
    int buf[BUFFER_SIZR];                          //定义缓冲区
    pthread_mutex_t mutex;                         //定义互斥量
    int readpos,writepos;                          //定义读端和写端
    pthread_cond_t full;                           //定义条件变量
    pthread_cond_t empty;
}PRODUCER;

具体代码实现

void init(PRODUCER *p)                                       /*初始化*/
{
    pthread_mutex_init(&p->mutex,NULL);
    pthread_cond_init(&p->empty,NULL);
    pthread_cond_init(&p->full,NULL);
    p->readpos = 0;
    p->writepos = 0;
}
void put(PRODUCER *p,int data)                            /*将数据写入缓冲区*/
{
    pthread_mutex_lock(&p->mutex);
    while((p->writepos+1) % BUFFER_SIZR == p->readpos)    //判断缓冲区是否已满
    {
        pthread_cond_wait(&p->full,&p->mutex);
    }
    p->buf[p->writepos++] = data;                         //缓冲区写入数据
    if(p->writepos >= BUFFER_SIZR)                        //读端置零
    p->writepos = 0;
    pthread_mutex_unlock(&p->mutex);
    pthread_cond_signal(&p->empty);                       //给消费者发送信号
}
int  get(PRODUCER *p)                                    /*获得缓冲区中的数据*/
{
    int data;
    pthread_mutex_lock(&p->mutex);
    while(p->readpos == p->writepos)                     //缓冲区是否为空
    pthread_cond_wait(&p->empty,&p->mutex);
    data = p->buf[p->readpos++];                        //缓冲区读出数据
    if(p->readpos >= BUFFER_SIZR)                       //写端置零
     p->readpos = 0;
     pthread_mutex_unlock(&p->mutex);
     pthread_cond_signal(&p->full);                     //给生产者发送信号
     return data;
}
PRODUCER buffer;
void *producer(void * data)                                              /*生产者输入数据*/
{
    int n;
    for(n = 0;n<10;n++)
    {
        printf("==生产者%d\n",n);
        put(&buffer,n);
    }
    put(&buffer,OVER);                                               //结束标志

}
void* consumer(void * data)                                         /*消费者获得数据*/
{
    int d;
    while(1)
    {
        d = get(&buffer);
        if(d == OVER)                                                //遇到结束标志,退出
        break;
        printf("--消费者%d\n",d);
    }
}
void destory(PRODUCER *p)                                            /*销毁*/
{
    pthread_mutex_destroy(&p->mutex);
    pthread_cond_destroy(&p->empty);
    pthread_cond_destroy(&p->full);
}
int main (int argc,char * argv[])
{
    pthread_t thid1,thid2;
    void * ret;
    init(&buffer);
    pthread_create(&thid1,NULL,(void*)&producer,NULL);               //创建相应线程
    pthread_create(&thid2,NULL,(void*)&consumer,NULL);
    pthread_join(thid1,&ret);                                        //等待线程结束
    pthread_join(thid2,&ret);
    destory(&buffer);
    return 0;
}

输出结果:
这里写图片描述
问题总结
当然除了条件变量和互斥锁,我们还可以通过信号量完成该模型的设计,大致思路都是一样的,信号量可以说是互斥锁的升级版,它可以实现多线程同时访问同一个数据区域,功能很强大,有兴趣的小伙伴可以自己试着实现哦。
文章难免有错误和不足的地方,欢迎小伙伴的提出和指正。

猜你喜欢

转载自blog.csdn.net/Cxinsect/article/details/81605339
今日推荐