zoukankan      html  css  js  c++  java
  • C语言之生产者与消费者模型

      

    多线程并发应用程序有一个经典的模型,即生产者/消费者模型。系统中,产生消息的是生产者,处理消息的是消费者,消费者和生产者通过一个缓冲区进行消息传递。生产者产生消息后提交到缓冲区,然后通知消费者可以从中取出消息进行处理。消费者处理完信息后,通知生产者可以继续提供消息。

    要实现这个模型,关键在于消费者和生产者这两个线程进行同步。也就是说:只有缓冲区中有消息时,消费者才能够提取消息;只有消息已被处理,生产者才能产生消息提交到缓冲区。

       我们用一个队列来做这个缓冲区,产生的消息我们放到这个队列中去,如果这个队列满了,则不放入消息,我们这个队列大小是10,能够存放10条消息。然后消费者去消费,消费者去这个缓冲区里去取数据,同样,如果缓冲区里没有数据,那么就不会消费。

      这一模型的核心就是消费者和生产者一起去抢互斥锁,谁抢到了这个锁谁就有资格对这个缓冲区进行相关操作。

     分析

      一线程负责生产数据,另一部分线程负责消费数据。

      问题1:如果产生的块,消费的慢,生产者容易饿死

      问题2:如果生产的慢,消费的快,消费者容易饿死

      只有把两个问题协调好,才能最大限度的提高效率。

    代码:

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

    #define MAX 20

    char storage[MAX] = {};
    int count = 0;

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t full = PTHREAD_COND_INITIALIZER;
    pthread_cond_t empty = PTHREAD_COND_INITIALIZER;

    void show_storage(char* role,char* op,char prod)
    {
    printf("%s:",role);
    for(int i=0; i<count; i++)
    {
    printf("%c",storage[i]);
    }
    printf("%s%c ",op,prod);
    }

    void* pro_run(void* arg)
    {
    char* who = "生产者";
    while(1)
    {
    pthread_mutex_lock(&mutex);
    while(count >= MAX)
    {
    printf("%s:满仓 ",who);
    pthread_cond_wait(&full,&mutex);
    }

    char prod = 'A'+rand()%26;
    storage[count++] = prod;

    show_storage(who,"->",prod);

    pthread_cond_signal(&empty);
    pthread_mutex_unlock(&mutex);

    usleep(rand()%100*1000);
    }
    }

    void* con_run(void* arg)
    {
    char* who = "消费者";
    while(1)
    {
    pthread_mutex_lock(&mutex);
    while(count <= 0)
    {
    printf("%s:空仓 ",who);
    pthread_cond_wait(&empty,&mutex);
    }

    char prod = storage[count--];

    show_storage(who,"<-",prod);

    pthread_cond_signal(&full);
    pthread_mutex_unlock(&mutex);

    usleep(rand()%100*1000);
    }
    }

    int main()
    {
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,pro_run,NULL);
    pthread_create(&tid2,NULL,con_run,NULL);
    getchar();
    }

    实现:

  • 相关阅读:
    java中&和&&是怎么运算的
    struts中ActionForward 使用mapping.findForward如何传递get参数
    EL表达式_详解
    JSTL标签_详解
    inner join, left join, right join, full join 的区别
    CentOS7部署FastDFS+nginx模块
    一个实例明白AutoResetEvent和 ManulResetEvent的用法
    C#防止在画面上闪烁的Button
    C#中给Label控件设置BackgroundImage属性
    浅析C#异步操作
  • 原文地址:https://www.cnblogs.com/1996-1-0-3-0/p/9408411.html
Copyright © 2011-2022 走看看