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;
}