1. 基於單鏈表的生產者與消費者模型
生產者—消費者模型的321原則:
3種關係:生產者-生產者 ***互斥*** 消費者-消費者 ***互斥*** 生產者-消費者 ***互斥,同步***
2種角色:
消費者 生產者
1個交易場所:
臨界資源
實現321的方法:
1個交易場所:創建一個帶頭節點的鏈表:
typedef struct _head //結構體聲明
{
int data;
struct _head *next;
}Node,*Node_p,**Node_pp;
Node_p head; //頭指針聲明
void InitList(Node_pp _h) //初始化帶頭節點鏈表
{
*_h =(Node_p)malloc(sizeof(Node));
(*_h)->next = NULL;
}
void PushFrond(Node_p _h,int K)//
{
Node_p tmp = _h->next;
_h->next =(Node_p)malloc(sizeof(Node));
_h = _h->next;
_h->data = K;
_h->next = tmp;
}
Node_p PopFrond(Node_p _h)
{
if(_h->next == NULL)
return NULL;
Node_p tail = _h->next;
_h->next = tail->next;
return tail;
}
兩個角色:我們需要創建兩個線程:
void *consume(void *arg) // 用於消費,即調用PopFrond
void &product(void *arg) //用於生產,即調用PushFrond
互斥:函數consume與product不能運行臨界區,即消費者,生產者不能同時訪問臨界資源(不能同時改變鏈表head):
我們可以用互斥鎖
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex_lock);//加鎖
pthread_mutex_unlock(&mutex_lock);//解鎖
同步:消費者不能超過生產者消費,當消費者發現沒有資源時,就掛起等待,當生產者放入資源後發送信號喚醒消費者消費;
可以用條件變量即同時滿足同步:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_cond_wait(&cond,&mutex_lock);//等待
pthread_cond_signal(&cond);//發信號
信號的功能:
1.釋放鎖 //讓其他線程訪問臨界區
2. 阻塞等待/
3. 喚醒時重新獲得鎖
消費者-生產者模型編寫:
void* product(void *arg)
{
while(1){
int n = rand()/12123;
pthread_mutex_lock(&mutex_lock); //解鎖訪問
PushFrond(head,n);
printf("product done! %d\n",n);
pthread_mutex_unlock(&mutex_lock);//解鎖
pthread_cond_signal(&cond);//生產完成,發送信號,消費者消費
sleep(2);
}
return NULL;
}
void *consum(void *arg)
{
while(1){
pthread_mutex_lock(&mutex_lock);//加鎖訪問
Node_p tmp = PopFrond(head);
while(tmp == NULL)//當沒有資源時,則阻塞等待
{
pthread_cond_wait(&cond, &mutex_lock);
tmp = PopFrond(head);
}
printf("consum done! %d\n",tmp->data);
pthread_mutex_unlock(&mutex_lock);//解鎖
}
return NULL;
}