一、概念
  生产者:产生数据的的模块。
  消费者:处理数据的模块。
  那么生产者产生数据之后,消费者怎么拿,从哪拿呢?所以,仅仅有这两个角色是不能完成我们期望的工作的。还需要一个缓冲区,像超市的货架一样,供货商(生产者)将商品摆到货架(缓冲区)上,购买者(消费者)从货架上拿走,这个货架也是必不可少的。
  试想如果没有缓冲区,生产者生产一个数据之后,必须等待消费者消费完成,生产者才能继续生产,那么如果生产者很快,而消费者很慢,那么只能让生产者干等。这好比让CPU和外设直接打交道,如果没有缓存,还不得慢死,白白浪费CPU时间。
  抽象出此模型如下:

  接下来说明三种关系:
  1.生产者与生产者之间:像供货商与供货商之间,存在明显的竞争关系,在操作系统上,我们称为互斥关系。
  2.消费者与消费者之间:同样是互斥的。
  3.生产者与消费者之间:首先必须保证,生产者在生产时,消费者不能来打扰,否则会出现数据二义性的问题。(生产者要往缓冲区里写入“1234”,刚写了12时消费者来缓冲区取数据了,那么它拿到的只能是12)。同时,消费者在消费时生产者也不能打扰,道理是一样的。所以,它们之间也有互斥的关系。除了互斥外,还必须保证生产者消费者按照一定的顺序访问资源。因为必须是让生产者先生产,消费者才能进行消费,类似于这样按照顺序访问资源成为同步,所以这两者之间还有同步的关系。
  二、模型模拟
  1.一个生产者一个消费者。
  我们使用两个线程分别模拟生产者和消费者,使用单链表作为缓冲区,每次让生产者PUSH数据到链表头,消费者也每次从链表头部取POP数据。
  完整的代码:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond=PTHREAD_COND_INITIALIZER;
typedef struct node
{
int _data;
struct node* _next;
}node,*pnode;
typedef struct Linklist
{
node * phead;
}Linklist,*pLinklist;
pnode creatNode(int data)
{
pnode newnode=(pnode)malloc(sizeof(node));
if(newnode==NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
newnode->_data=data;
newnode->_next=NULL;
return newnode;
}
void initList(pLinklist plist)
{
assert(plist);
//pLinklist head=(pLinklist)malloc(sizeof(Linklist));
//  plist=head;
plist->phead=NULL;
}
void pushHead(pLinklist list,int data)
{
assert(list);
pnode newnode=creatNode(data);
if(list->phead==NULL)
{
list->phead=newnode;
return;
}
newnode->_next=list->phead;
list->phead=newnode;
}
void popHead(pLinklist list,int* data)
{
assert(list);
if(list->phead==NULL)
{
printf("list empty! ");
return;
}
pnode del=list->phead;
*data=del->_data;
list->phead=del->_next;
del->_next=NULL;
free(del);
}
void destoryList(pLinklist list)
{
assert(list);
if(list->phead!=NULL)
{
pnode cur =list->phead;
while(cur)
{
pnode del=cur;
cur=cur->_next;
free(del);
del=NULL;
}
}
list->phead=NULL;
}
void showList(pLinklist list)
{
assert(list);
pnode cur=list->phead;
while(cur!=NULL)
{
printf("%d ",cur->_data);
cur=cur->_next;
}
printf(" ");
}
void* producter_thread(void* arg)
{
pLinklist list=(pLinklist)arg;
while(1)
{
sleep(1);
pthread_mutex_lock(&mylock);   //访问临界区前加锁
pushHead(list,rand()%1000);
pthread_cond_signal(&mycond);   //生产完毕唤醒等待在该条件变量下的线程
pthread_mutex_unlock(&mylock);  //访问结束解锁
printf("producter success %d ",list->phead->_data);
}
}
void* consumer_thread(void* arg)
{
pLinklist list=(pLinklist)arg;
while(1)
{
sleep(1);
pthread_mutex_lock(&mylock);  //加锁
int data=0;
while(list->phead==NULL)
{
pthread_cond_wait(&mycond,&mylock);  //若链表中无数据,则消费者需要等待。
}
popHead(list,&data);
pthread_mutex_unlock(&mylock);    //解锁
printf("consumer success %d ",data);
}
}
int main()
{
Linklist list;
initList(&list);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,producter_thread,(void*)&list);//创建线程
pthread_create(&tid2,NULL,consumer_thread,(void*)&list);
pthread_join(tid1,NULL);   //等待线程结束回收线程
pthread_join(tid2,NULL);
destoryList(&list);
return 0;
}