生产者消费者模型

生产者消费者模型遵循三二一原则
三种关系:生产者和生产者 :互斥
消费者和消费者:互斥
生产者和消费者:同步与互斥
两种角色
一个交易场所

条件变量的作用:判断临界资源中生产消费的条件是否成熟

通常情况下互斥锁和条件变量搭配使用

对单链表的操作
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
typedef struct Node
{
    int data;
   struct Node* next;
}Node,**ppNode;
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
Node*  pHead=NULL;
Node*GetNode(int val)
{
     Node*tmp=(Node*)malloc(sizeof(Node));
     if(tmp==NULL)
     {
          perror("malloc");
          return NULL;
     }
     tmp->data=val;
     tmp->next=NULL;
     return tmp;
}
void InitList(ppNode p)
{
     *p=GetNode(0);
}
void PushFront(Node* pHead,const int data)
{
   Node*tmp=GetNode(data);
   tmp->next=pHead->next;
   pHead->next=tmp;
}
void PopFront(Node* pHead,int*out)
{
     Node*tmp=pHead->next;
     if(tmp)
     {
         Node*next=tmp->next;
         pHead->next=next;
          *out=tmp->data;
         free(tmp);
          tmp=NULL;
     }
}
void *product(void *arg)
{
     while(1)
     {
        int data=rand()%1000;
        pthread_mutex_lock(&lock);
        PushFront(pHead,data);
        pthread_mutex_unlock(&lock);
        pthread_cond_signal(&cond);
        printf("product done:%d\n!",data);
        sleep(1);
     }
}
void *consume(void*arg)
{
     while(1)
     {
          int c=-1;
      pthread_mutex_lock(&lock);
       while(pHead->next==NULL)
       {
            printf("consume is waiting!\n");
            pthread_cond_wait(&cond,&lock);
       }
       PopFront(pHead,&c);
       pthread_mutex_unlock(&lock);
       printf("consume is done :%d\n",c);
     }
}
int main()
{
    InitList(&pHead);
     pthread_t tproduct;
     pthread_t tconsume;
     pthread_create(&tproduct,NULL,product,NULL);
     pthread_create(&tconsume,NULL,consume,NULL);
     pthread_join(tproduct,NULL);
     pthread_join(tconsume,NULL);
     pthread_mutex_destroy(&lock);
     pthread_cond_destroy(&cond);
   return 0;
}

这里写图片描述

这里写图片描述

我们可以通过信号量来实现
sem_wait()可以获得资源(P操作),使semaphore的值减1,如果调⽤用sem_wait()时 semaphore的值 已经是0,则挂起等待。如果不希望挂起等待,可以调⽤用sem_trywait() 。调⽤用 sem_post() 可以释放资源(V操作),使semaphore 的值加1,同时唤醒挂起等待的线程。总的来说也是通过信号量来实现同步
初始化一个线程使用sem_init

#include <semaphore.h>
 int sem_init(sem_t *sem, int pshared, unsigned int value);
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
#include<stdio.h>
#include<pthread.h>
#include <semaphore.h>
#define SIZE 10
sem_t data_sem;
sem_t blank_sem;
int arr[SIZE]={0};
void* product(void*argv)
{
     int ret=0;
     int i=0;
    while(1)
     {
          sem_wait(&blank_sem);
          arr[i++]=ret;
          sem_post(&data_sem);
          printf("product done:%d!\n",ret++);
          i%=SIZE;
     }
}
void* consume(void*argv)
{
     int i=0;
     while(1)
     {
      sem_wait(&data_sem);
       int ret=arr[i++];
       sem_post(&blank_sem);
       printf("consume done:%d\n",ret);
       i%=SIZE;
       sleep(1);
     }
}
int main()
{
     pthread_t p;
     pthread_t c;
    sem_init(&data_sem,0,0);
     sem_init(&blank_sem,0,SIZE);
     pthread_create(&p,NULL,product,NULL);
     pthread_create(&c,NULL,consume,NULL);
     pthread_join(p,NULL);
     pthread_join(c,NULL);
     sem_destroy(&data_sem);
     sem_destroy(&blank_sem);
     return 0;
}

这里写图片描述
针对多生产者多消费者的模型:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
必须要加锁
生产者和生产者是互斥的
消费者和消费者互斥的
生产者和消费者要满足不套圈,消费者不能超过生产者

#include<stdio.h>
#include<pthread.h>
#include <semaphore.h>
#define SIZE 10
sem_t data_sem;
sem_t blank_sem;
static int i=0;
static int ret=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int arr[SIZE]={0};
void* product(void*argv)
{
    while(1)
    {
        sem_wait(&blank_sem);
        pthread_mutex_lock(&mutex);
        arr[i++]=ret;
        sem_post(&data_sem);
        printf("product done:ret=%d!\n",i,ret++);
        i%=SIZE;
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}
void* consume(void*argv)
{
    int ret=0;
   static int i=0;
    while(1)
    {
      sem_wait(&data_sem);
      pthread_mutex_lock(&mutex);
      int ret=arr[i++];
      sem_post(&blank_sem);
      printf("consume done:ret=%d\n",i,ret);
      i%=SIZE;
      pthread_mutex_unlock(&mutex);
      //sleep(1);
    }
}
int main()
{
    pthread_t p1;
    pthread_t p2;
    pthread_t c1;
    pthread_t c2;
    sem_init(&data_sem,0,0);
    sem_init(&blank_sem,0,SIZE);
    pthread_create(&p1,NULL,product,NULL);
    pthread_create(&p2,NULL,product,NULL);
    pthread_create(&c1,NULL,consume,NULL);
    pthread_create(&c2,NULL,consume,NULL);
    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    pthread_join(c1,NULL);
    pthread_join(c2,NULL);
    sem_destroy(&data_sem);
    sem_destroy(&blank_sem);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值