1、生产者与消费者问题

  空间满:生产者不能生产数据;

  空间空:消费者不能取出数据;

  在这种模型下,将会有(生产者:消费者)为:一对一、一对多、多对一、多对多。

  为了简化问题,在这里就只实现一个生产者和一个消费者的问题。

模型如下

wKiom1fjAGbwvJgJAAAjtPima4g711.png-wh_50

注意:

  (1)、线程阻塞时,用条件变量来解决。唤醒并运行其后的语句是在遇到阻塞之后;

  (2)、临界区模式;

  pthread_mutex_lock(&mutex);
  //临界区
  pthread_cond_wait(&cond, &mutex); //该函数将自动解锁,此处将会发生阻塞。

  ......

  pthread_mutex_unlock(&mutex);

  (3)、本题还可以采用双缓冲区;

2、代码实现

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

#define BUF_SIZE    8   //一个开辟8个数组元素空间
#define MAX_NUM     20   //将一共产生20个数据

struct PC{   //生产者与消费者结构体
    pthread_mutex_t mutex;  //互斥量
    pthread_cond_t noempty;  //条件变量,数组不空
    pthread_cond_t nofull;   //条件变量,数组不满
    int buf[BUF_SIZE];  //开辟空间
    int nput;  //数组下标
    int nval;  //要存放的数据
    int size;  //统计当前数组空间大小
}shared = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER};

void* producer(void *arg){
    for(;;){
        pthread_mutex_lock(&shared.mutex);
        if(shared.nval > MAX_NUM){
            pthread_mutex_unlock(&shared.mutex);
            break;
        }
        shared.buf[shared.nput] = shared.nval;
        shared.nput++;
        shared.nval++;
        shared.size++;

        if(shared.nput >= BUF_SIZE){
            shared.nput = 0;  //下标始终在0-7
        }
        if(shared.size >= BUF_SIZE){ 
            pthread_cond_wait(&shared.nofull, &shared.mutex);
        }else{
            pthread_cond_signal(&shared.noempty);
        }
        pthread_mutex_unlock(&shared.mutex);
    }
}

void *customer(void *arg){
    int value;
    int i = 0;
    for(;;){
        pthread_mutex_lock(&shared.mutex);
        value = shared.buf[i];
        i++;
        printf("value = %d\n", value);   
        if(value >= MAX_NUM){
            pthread_mutex_unlock(&shared.mutex);
            break;
        }
        sleep(1);

        if(i >= BUF_SIZE){
            i = 0;
        }
        shared.size--;
        if(shared.size == 0){
            pthread_cond_wait(&shared.noempty, &shared.mutex);
        }else{
            pthread_cond_signal(&shared.nofull);
        }

        pthread_mutex_unlock(&shared.mutex);
    }
}

void initPc(void){  //对结构体成员初始化
    memset(shared.buf, 0, BUF_SIZE);   
    shared.nput = 0;  //下标从0开始
    shared.nval = 1;  //存放的数据从1开始
    shared.size = 0;  //数组空间大小为0
}

int main(void){
    initPc();
    pthread_t pid, cid;
    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, customer, NULL);

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

    return 0;
}

运行结果

wKioL1fjAsPhDyLOAAB0-4_dass010.png-wh_50

  对以上的代码模式解读:首先是生产者生产,在空间满了之后,阻塞等待,此时,消费者在读取数据,等到读取为空的时候,唤醒生产者生产,最后,在生产完了的时候,消费者读取完成,将一起退出for循环。

这里的同步就是利用了锁机制完成的(通过互斥量和条件变量)。