多线程之生产者消费者模型

1、描述一下生产者消费者模型。
有n个生产者线程生产产品,m个消费者线程消费产品。在这里他们需要互斥地访问产品。

2、为什么要把产品数量设入临界区,如何实现临界区的(如何调用相关API)?
因为如果在资源抢占过程中,恢复现场时会覆盖另一个线程对产品数量的操作结果。
在Linux下,调用pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)对临界区加锁解锁。

3、在临界区内是如何避免死锁的。并请你深入操作系统内核层面剖析一下其中原理。
定义产品数量为g_num一个消费者进程进入临界区后
if(g_num == 0){丢弃锁}
线程通过调用pthread_cond_wait(&g_cond, &g_mutex)来进行丢弃锁。
在调用pthread_cond_wait()后,操作系统做了三件事情。
第一步线程丢锁,然后线程休眠,第三步线程等待苏醒。线程需要用另一个API来唤醒。thread_cond_signal()。

4、请编码实现生产者消费者模型。并将产品数量控制在20以内。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#define CUSTOMER_COUNT 2
#define PRODUCTER_COUNT 4
int g_num = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义锁
pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;//定义条件并初始化
void* customer(void* arg)//消费者线程
{
    int inum = 0;
    inum = *(int *)arg;
    while (1)
    {
        pthread_mutex_lock(&mutex); //线程获得锁,进入临界区
        printf("cumstomer:%d\n", inum);
        while (g_num == 0)
        {
            printf("\nwaiting start\n");
            pthread_cond_wait(&my_condition, &mutex);//条件锁
            printf("waiting end\n");
        }
        printf("customer run\n");
        g_num--;//消费产品
        printf("customer end\n");
        pthread_mutex_unlock(&mutex);//线程释放锁,退出临界区
        sleep(1);
    }
    pthread_exit(0);
}

void* producter(void* arg)//生产者线程
{
    int inum = 0;
    inum = *(int *)arg;
    while (1)
    {
        pthread_mutex_lock(&mutex);//线程获得锁,创建临界区,判断产品数量
        if (g_num > 20)
        {
            printf("Product:%d too much.\n", g_num);
            pthread_mutex_unlock(&mutex);
            sleep(1);
            continue;
        }
        else
        {
            pthread_mutex_unlock(&mutex);
        }
        pthread_mutex_lock(&mutex);//获得锁,进入临界区
        printf("producter:%d\n", inum);
        printf("The num of g_num:%d\n", g_num);
        printf("producter run\n");
        g_num++;//生产产品
        printf("producter end\n");
        pthread_cond_signal(&my_condition);//产出产品,唤醒等待线程
        pthread_mutex_unlock(&mutex);//释放锁,退出临界区
        sleep(1);
    }
    pthread_exit(0);
}
int main()
{
    int i = 0;
    pthread_t threadArray[CUSTOMER_COUNT + PRODUCTER_COUNT + 10];//线程数组

    for (i = 0; i < PRODUCTER_COUNT; i++)//创建生产者线程
    {
        pthread_create(&threadArray[i], NULL, producter, (void*)&i);
    }

    for (i = 0; i < CUSTOMER_COUNT; i++)//创建消费者线程
    {
        pthread_create(&threadArray[i + CUSTOMER_COUNT], NULL, customer, (void*)&i);
    }

    for (i = 0; i < PRODUCTER_COUNT + CUSTOMER_COUNT; i++)//等待线程结束
    {
        pthread_join(threadArray[i], NULL);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/naughfy/article/details/72368973