多線程之生產者消費者模型

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;
}
發佈了36 篇原創文章 · 獲贊 16 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章