天天看點

經典生産者與消費者問題(線程的同步與互斥)

線上程世界裡,生産者就是生産資料的線程,消費者就是消費資料的線程。在多線程開發當中,如果生産者處理速度很快,而消費者處理速度很慢,那麼生産者就必須等待消費者處理完,才能繼續生産資料。同樣的道理,如果消費者的處理能力大于生産者,那麼消費者就必須等待生産者。為了解決這個問題于是引入了生産者和消費者模式。

互斥:保證一個資源隻能被一個程序使用。

首先,解釋“321”:

1、一個交易場所(緩沖區,類似于超市)

2、兩種角色:生産者(生産資料)與消費者(消費資料)

3、三種關系:生産者與生産者互斥

消費者與消費者互斥

生産者與消費者同步與互斥

在未做任何處理之前讓生産者生産資料,消費者消費資料,就會出現以下問題:

經典生産者與消費者問題(線程的同步與互斥)

參考代碼:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>
typedef struct Node
{
  int _data;
  struct Node *next;
}node,*pnode,**ppnode;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pnode phead=NULL;
pnode alloc(int data)
{
  pnode temp=(pnode)malloc(sizeof(node));
  if(temp==NULL)
  return NULL;
  temp->_data=data;
  temp->next=NULL;
  return temp;
}
void initList(ppnode phead)
{
   *phead=alloc();
}
void pushList(pnode phead,int data)
{
    pnode _p=alloc(data);
    _p->next=phead->next;
    phead->next=_p;
}
int  popList(pnode phead)
{

   if(phead->next==NULL)
   {
       return -;
   }
   else
   {
   pnode temp=phead->next;
   int data=temp->_data;
   phead->next=temp->next;
   free(temp);
   return data;
   temp=NULL;
   }
   return ;
}
void destroyList(pnode phead)
{
  while(phead->next)
  {
    pnode temp=phead->next;
    phead->next=temp->next;
    free(temp);
  }
}
void showList(pnode phead)
{
  pnode temp=phead->next;
  while(temp)
  {
    printf("%d",temp->_data);
    temp=temp->next;
  }
  printf("\n");
}
void* producter(void* arg)
{
  int data=;
  while()
  {
   sleep();
   data=rand()%;
   pushList(phead,data);
   printf("producter:%d\n",data);
  }
  return (void*);
}
void* consumer(void* arg)
{                                                                   
  int data=;
  while()
  {
      sleep();
    if(data=popList(phead))
    {
      printf("consumer:%d\n",data);
    }
  }
  return (void*);
}
int main()
{
    initList(&phead);
    /*pushList(phead,1);
    pushList(phead,2);
    pushList(phead,3);
    pushList(phead,4);
    showList(phead);
    popList(phead);
    showList(phead);*/
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL,producter,NULL);
    pthread_create(&tid2,NULL,consumer,NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    destroyList(phead);
    return ;
}
           

運作結果:

經典生産者與消費者問題(線程的同步與互斥)
經典生産者與消費者問題(線程的同步與互斥)

為了保證原子性通路臨界資源,故引入加互斥鎖。

參考代碼:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>
typedef struct Node
{
  int _data;
  struct Node *next;
}node,*pnode,**ppnode;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pnode phead=NULL;
pnode alloc(int data)
{
  pnode temp=(pnode)malloc(sizeof(node));
  if(temp==NULL)
  return NULL;
  temp->_data=data;
  temp->next=NULL;
  return temp;
}
void initList(ppnode phead)
{
   *phead=alloc();
}
void pushList(pnode phead,int data)
{
    pnode _p=alloc(data);
    _p->next=phead->next;
    phead->next=_p;
}
int  popList(pnode phead)
{

   if(phead->next==NULL)
   {
       return -;
   }
   else
   {
   pnode temp=phead->next;
   int data=temp->_data;
   phead->next=temp->next;
   free(temp);
   return data;
   temp=NULL;
   }
   return ;
}
void destroyList(pnode phead)
{
  while(phead->next)
  {
    pnode temp=phead->next;
    phead->next=temp->next;
    free(temp);
  }
}
void showList(pnode phead)
{
  pnode temp=phead->next;
  while(temp)
  {
    printf("%d",temp->_data);
    temp=temp->next;
  }
  printf("\n");
}
void* producter(void* arg)
{
  int data=;
  while()
  {
   sleep();
   pthread_mutex_lock(&lock);
   data=rand()%;
   pushList(phead,data);
   printf("producter:%d\n",data);
   pthread_mutex_unlock(&lock);
  }
  return (void*);
}
void* consumer(void* arg)
{                                                                   
  int data=;
  while()
  {
      sleep();
    pthread_mutex_lock(&lock);
    if(data=popList(phead))
    {
      printf("consumer:%d\n",data);
      pthread_mutex_unlock(&lock);
    }
  }
  return (void*);
}
int main()
{
    initList(&phead);
    /*pushList(phead,1);
    pushList(phead,2);
    pushList(phead,3);
    pushList(phead,4);
    showList(phead);
    popList(phead);
    showList(phead);*/
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL,producter,NULL);
    pthread_create(&tid2,NULL,consumer,NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_mutex_destroy(&lock);
    destroyList(phead);
    return ;
}
           

運作結果:

經典生産者與消費者問題(線程的同步與互斥)

但互斥鎖隻能解決互斥問題,保證原子性操作,還是不能解決同步問題,故引入條件變量(Condition Variable )。

參考代碼:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<pthread.h>
typedef struct Node
{
  int _data;
  struct Node *next;
}node,*pnode,**ppnode;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pnode phead=NULL;
pnode alloc(int data)
{
  pnode temp=(pnode)malloc(sizeof(node));
  if(temp==NULL)
  return NULL;
  temp->_data=data;
  temp->next=NULL;
  return temp;
}
void initList(ppnode phead)
{
   *phead=alloc();
}
void pushList(pnode phead,int data)
{
    pnode _p=alloc(data);
    _p->next=phead->next;
    phead->next=_p;
}
int  popList(pnode phead)
{

   if(phead->next==NULL)
   {
       return -;
   }
   else
   {
   pnode temp=phead->next;
   int data=temp->_data;
   phead->next=temp->next;
   free(temp);
   return data;
   temp=NULL;
   }
   return ;
}
void destroyList(pnode phead)
{
  while(phead->next)
  {
    pnode temp=phead->next;
    phead->next=temp->next;
    free(temp);
  }
}
void showList(pnode phead)
{
  pnode temp=phead->next;
  while(temp)
  {
    printf("%d",temp->_data);
    temp=temp->next;
  }
  printf("\n");
}
void* producter(void* arg)
{
  int data=;
  while()
  {
   sleep();
   pthread_mutex_lock(&lock);
   data=rand()%;
   pushList(phead,data);
   printf("producter:%d\n",data);
   pthread_cond_signal(&cond);
   printf("data has been producted!\n ");
   pthread_mutex_unlock(&lock);
  }
  return (void*);
}
void* consumer(void* arg)
{                                                                   
  int data=;
  while()
  {
      sleep();
    pthread_mutex_lock(&lock);
    while(phead->next==NULL)
    {
      printf("No data is producted!\n");
      pthread_cond_wait(&cond,&lock);
    }
      data=popList(phead);  
      printf("consumer:%d\n",data);
      pthread_mutex_unlock(&lock);
  }
  return (void*);
}
int main()
{
    initList(&phead);
    /*pushList(phead,1);
    pushList(phead,2);
    pushList(phead,3);
    pushList(phead,4);
    showList(phead);
    popList(phead);
    showList(phead);*/
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL,producter,NULL);
    pthread_create(&tid2,NULL,consumer,NULL);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
    destroyList(phead);
    return ;
}
           

運作結果:

經典生産者與消費者問題(線程的同步與互斥)

繼續閱讀