生产者和消费者代码实现

信号量实现生产者和消费者模型

       有一块固定容量的缓存区,有多个线程同时访问或操作这个块缓存区,而此时,一个线程称为生产者,生成数据到这块缓存,另一个线程消费者从这个块缓存里读取数据,这个过程就可能引发一系列线程安全问题。而解决问题的关键就是,使消费者和生产者同时只能有一个线程访问这块缓存,也就是说它们之间是互斥的。

方法一:信号量

信号量设置的初始值可以不为1,假设一开始设置信号零的初始值为3;

当第一个线程访问共享资源,那sem的值减一等于2,第二个线程访问共享资源的话在减一等于1,第三个线程访问共享资源在减一等于0,那此时,如果这三个线程都还没有解锁,那么就会阻塞,直到有一个线程解锁信号量加一,下一个线程才可以访问共享资源,这三个访问共享资源的线程是并行访问的,相比于互斥锁而言,提高了效率。

关于信号量的详解点击https://blog.csdn.net/choudan8888/article/details/98518457

方法二:条件变量

       当没有可以可消费的食物时,消费者阻塞,等待生产者生产,当生产者生产出产品的时候提醒消费者有东西可以吃了,然后消费者接触阻塞。

关于条件变量的详解点击https://blog.csdn.net/choudan8888/article/details/98474559

 

代码实现


  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 #include<string.h>
  5 #include<semaphore.h>
  6 
  7 //定义两个信号量
  8 sem_t producer_sem;
  9 sem_t customer_sem;
 10 
 11 //定义节点
 12 typedef struct Node
 13 {
 14     int data;
 15     struct Node *next;
 16 }Node;
 17 
 18 Node *head = NULL;
 19 void* producer()
 20 {
 21     while(1)
 22     {
 23       
 23         //一开始,生产者要生产,所以信号量减一
 24         sem_wait(&producer_sem);   //--
 25         Node *p = (Node *)malloc(sizeof(Node));
 26         p->data = rand()%1000;
 27         p->next = head;
 28         head = p;

 29         printf("producer = %d\n",head->data);
 30         //当生产完成之后,需要提醒消费者可以消费了,也释放自己占用的信号量
 31         sem_post(&customer_sem);   //++
 32         sleep(rand()%3);
 33     }
 34 
 35     return NULL;
 36 }
 37 
 38 void *customer()
 39 {
 40     while(1)
 41     {
 42         //当信号量不是0的时候,消费者就可以访问共享资源,占用一个信号量,信>    号量减一
 43         sem_wait(&customer_sem);  //--
 44 
 45         Node *p = head->next;
 46         printf("customer = %d\n",head->data);
 47         free(head);
 48         head = p;
 49         //用完之后释放解锁,提醒生产者有多余的信号量,
 50         sem_post(&producer_sem);   //++

 51         sleep(rand()%3);
 52     }
 53 }
 54 
 55 
 56 int main()
 57 {
 58     pthread_t p1,p2;
 59     //创建两个线程
 60     pthread_create(&p1,NULL,producer,NULL);
 61     pthread_create(&p2,NULL,customer,NULL);
 62
 63     //初始化生产者信号量,有四个线程操作共享资源
 64     sem_init(&producer_sem,0,4);
 65     //初始化消费者信号量,一开始没有资源,所以消费者一开始阻塞
 66     sem_init(&customer_sem,0,0);
 67 
 68 
 69     //释放信号狼
 70     sem_destroy(&producer_sem);
 71     sem_destroy(&customer_sem);
 72 
 73 
 74 
 75     //等待回收线程
 76     pthread_join(p1,NULL);
 77     pthread_join(p2,NULL);
 78 
 79     return 0;
 80 }

条件变量实现生产者和消费者模型

 


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

 
//线程同步需要互斥锁
pthread_mutex_t mutex;


//阻塞线程需要条件变量
pthread_cond_t cond;
typedef struct Node
{
    int data;
    struct Node *next;
}Node;

Node* head = NULL;

void * producer()
{
    while(1)
    {      
        Node *p = (Node *)malloc(sizeof(Node));
        p->data = rand()%1000;

        //开始枷锁,保护共享资源
        pthread_mutex_lock(&mutex);
        p->next = head;
        head = p;
        //开始解锁
        printf("producer pthid = %lu,%d\n",pthread_self(),p->data);             
        pthread_mutex_unlock(&mutex);
        //通知阻塞的线程
        pthread_cond_signal(&cond);
        sleep(rand()%3);
    }

        return NULL;
}

 
void * customer()
{   
    while(1)
    {
        //枷锁
        pthread_mutex_lock(&mutex);
        if(head == NULL)
        {
            //continue;
            //在这里做了三件事情阻塞线程,对互斥锁解锁,让生产者那边加锁,生产出东西后返回回来又对互斥锁继续枷锁
            pthread_cond_wait(&cond,&mutex);
 
        }
  
        printf("sustomer pthid = %-lu,%d\n",pthread_self(),head->data);
        Node*p = head->next;
        free (head);
        head = p;
        //解锁      
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main()
{
    //创建两个线程,一个生产,一个消费
    pthread_t p1,p2;
    pthread_create(&p1,NULL,producer,NULL);
    pthread_create(&p2,NULL,customer,NULL);
    //初始化条=条件变量和互斥锁
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);

 

    //回收子线程
    pthread_join(p1,NULL);
    pthread_join(p2,NULL);
    //销毁条件变量和互斥锁
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;

}

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值