【Linux】生产者消费者模型

    想要直到什么是生产者消费者模型首先要了解两个概念:同步和互斥。
    互斥:由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥,理解起来就是一个用这份资源的话另一个就不能用,这两者之间就是互斥关系
    同步:指的是多个进程协同完成同一项任务
    下面正式介绍生产者消费者模型:
    生产者消费者问题:
也叫缓存绑定问题,是一个经典的多进程同步问题
分为单生产者单消费者和多生产者多消费者两种情况,
    先来介绍一下生产者消费者模型中的两个重要角色:
生产者顾名思义,是一个产生数据的进程,而消费者是一个读出数据的进程,

对于单生产者单消费者模式,生产者产生一块数据后,放进缓冲池中,这时消费者看到缓冲池中有数据就可以来拿,如果生产者生产比消费者消费的快,消费者拿完缓冲池中所有数据之后就应该开始等待,等到有数据之后消费者才来消费,如果生产者生产比消费者消费的快,很快就将缓冲池装满了,生产者这时就不再产生数据,等消费者消费一块数据然后生产者再向里面装一块数据。

对于多生产者多消费者问题,就是在生产者之间和消费者之间添加互斥关系,其它和单生产者单消费者相同。

或许概念理解起来比较抽象,不过我们可以类比:

我们将缓冲池类比成超市,而超市的供货商就是生产者,而我们这些买东西的人就是消费者,
单消费者单生产者问题就可以类比为,这家超市只卖一种东西,这里就假设是方便面吧,这家超市小了一点只有一个货架,而且老板脾气比较古怪,只卖一种口味的,而这家超市是方圆百里唯一一家卖东西的,而只有一个人买东西哎,当供货商没有往货架上放方便面的时候即使我们再想吃也没办法,我们只能等,而货架的大小是固定的,供货商如果一次性发货太多了,但是货架只有一个,最多也只能做到将货架塞满,其他的只能等着,等有人来买走一包,然后才能往货架上再新添一包。

多生产者多消费者问题就可以类比为,有多个供货商不过还是这家超市,货架还是那么大,多个供货商都往货架上放方便面,但是货架的空间用一个就少一个意味着一个供销商在这个位置放了,另一个供销商就不能往这个位置放了,反正就是一个空位置只能供一个供销商使用,当前位置要是有东西了,只能考虑下一个位置是不是空的,是空的即可以放,不是空的就继续考虑下一个位置,如果放满了就等待,等到有人买走了再次有空位置了才可以放,对于每一个位置,各个供销商之间的关系就是一种互斥关系,而这时买东西的人也不是一个了,有很多个,但对于每个位置,你拿了别人就不能拿了,因为那个位置已经空了,只能看看下个位置有没有你要的方便面,没有的话再向后找,如果找到头也没有就只能等着有某一家供销商放上去了然后你才能拿。对于我们这些消费者针对于每一个位置上的方便面,我们之间存在的也是互斥关系。
我们利用线程同步互斥来实现一下简单的生产者消费者模型:

#include
#include
#include
#include
#define CUSTOMERS_COUNT 2
#define PRODUCERS_COUNT 2
struct msg{
    struct msg *next;
    int num;
};
struct msg *head = NULL;

pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_t threads[CUSTOMERS_COUNT+PRODUCERS_COUNT];
void * consumer(void * p)
{
    int num = *(int *)p;
    free(p);
    struct msg *mp;
    for(;;)
    {
        pthread_mutex_lock(&mutex);
        while(head == NULL)
        {
            printf("%d begin wait a condition...\n",num);
            pthread_cond_wait(&cond, &mutex);
        }
        printf("%d end wait a condition...\n",num);
        printf("%d begin consume product...\n", num);
        mp = head;
        head = mp->next;
        pthread_mutex_unlock(&mutex);
        printf("Consume %d\n", mp->num);
        free(mp);
        printf("%d end consume product...\n",num);
        sleep(rand()%5);
    }
}
void *producer(void *p)
{
    struct msg* mp;
    int num = *(int *)p;
    free(p);
    for(;;)
    {
        printf("%d begin produce product...\n", num);
        mp = (struct msg*)malloc(sizeof(struct msg));
        mp->num = rand()%1000+1;
        printf("produce %d\n", mp->num);
        pthread_mutex_lock(&mutex);
        mp->next = head;
        head = mp;
        printf("%d end produce product...\n",num);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        sleep(rand()%5);
    }
}
int main()
{
    srand(time(NULL));

    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    int i;
    for(i=0; iint *p = (int *)malloc(sizeof(int ));
        *p=i;
        pthread_create(&threads[i],NULL, consumer, (void*)p);

    }

    for(i=0; iint*p = (int*)malloc(sizeof(int));
        *p=i;
        pthread_create(&threads[CUSTOMERS_COUNT+i], NULL, producer, (void *)p);

    }

    for(i=0; i

一个线程模拟生产者生产数据,一个线程模拟消费者不断消费数据,并对生产和消费的过程进行加锁,保证原子性,保证不会出现互斥问题

你可能感兴趣的:(Linux)