㈠ 請高手幫忙解釋下這多線程的源代碼,每句注釋下 #include <stdio.h> #include <stdlib.h>
首先這是一個生產者和消費者問題。
生產者procer負責產生數據,然後通過put操作將數據放到緩沖區buf中。
消費者consumer負責顯示數據,通過get操作從緩沖區buf中讀取數據。
========》
先看主函數main(),
生產者和消費者分別用兩個線程來實現。
主函數中的pthread_create()函數就是用來創建這兩個線程的。
開始定義了兩個變數th_a,th_b用來記錄這兩個線程的線程號。
線程的程序體分別是procer,consumer。
接下來的pthread_join用來等待兩個線程結束。因為如果不等待,main函數的主線程會立即結束,而兩個子線程還來不及完全執行。
=======》
下面來分別看procer,consumer這兩個線程。
procer循環一百次,每次調用put往buffer中放數據,最後放一個OVER;
consumer循環用get從buffer中讀到數據並列印,直到讀取的數據位OVER數據時結束。
=======》
我們再分別來看put操作和get操作。
由於put和get都要訪問buf,buf就是一個臨界資源,為了解決這個臨界資源,在使用buf之前,要對它加鎖。
pthread_mutex_lock(b->lock)一個為信號量加鎖的函數。每個信號量只能加鎖一次(我說的可能不準確),如果執行該函數的時候,參數中的信號量已經被加鎖,則該函數阻塞,直到信號量被解鎖才繼續執行。這樣就能保證信號量所保護的臨界資源能夠被互斥的訪問。
structprodcons{
intbuffer[BUFFER_SIZE];/*這個就是循環緩沖區*/
pthread_mutex_tlock;/*這個是信號量,用來保證對緩沖區的互斥訪問*/
intreadpos,writepos;/*這兩個成員分別表示讀位置和寫位置*/
pthread_cond_tnotempty;/*這是表示緩沖區「非空」的條件信號量*/
pthread_cond_tnotfull;/*這是表示緩沖區「非滿」的條件信號量*/
};
buf是一個循環的緩沖區,我們先來看緩沖區為空和滿這兩種狀態時,讀、寫標記(readpos,writepos)的位置。
緩沖區為空時,readpos和writepos指在同一位置;
換從去為滿時,writepos位置的下一個位置就是readpos。
/*put負責把數據放到緩沖區*/
voidput(structprodcons*b,intdata)
{
//首先對互斥信號量進行加鎖
pthread_mutex_lock(&b->lock);
/*這里就是判斷緩沖區有沒有滿,用writepos+1與readpos比較,可以參考附圖。
*因為是循環緩沖區,所以要模BUFFER_SIZE。
*如果緩沖區滿,將在while中等待,直到緩沖區非滿,再繼續執行。
*/
while((b->writepos+1)%BUFFER_SIZE==b->readpos){
printf("waitfornotfull ");
//如果已經滿了,則等待消費者讀取了數據後發出「非滿」信號。
pthread_cond_wait(&b->notfull,&b->lock);
}
/*當緩沖區非滿時,將數據寫入緩沖區中writepos對應的位置*/
b->buffer[b->writepos]=data;
//更新writepos到下一個位置
b->writepos++;
//循環利用緩沖區空間,如果超過了最大值,則從頭開始。
if(b->writepos>=BUFFER_SIZE)b->writepos=0;
/*向消費者發送信號,告訴消費者緩沖取非空*/
pthread_cond_signal(&b->notempty);
//對互斥信號進行解鎖。
pthread_mutex_unlock(&b->lock);
}
/*--------------------------------------------------------*/
/*get負責從緩沖區中讀取數據*/
intget(structprodcons*b)
{
intdata;
//對互斥信號量進行加鎖
pthread_mutex_lock(&b->lock);
/*判斷緩沖區是否為空,為空則等待*/
while(b->writepos==b->readpos){
printf("waitfornotempty ");
pthread_cond_wait(&b->notempty,&b->lock);
}
/*讀取readpos位置的數據*/
data=b->buffer[b->readpos];
//更新readpos到下一個位置。
b->readpos++;
//循環利用緩沖區,回撥指針
if(b->readpos>=BUFFER_SIZE)b->readpos=0;
/*發信號給生產者,緩沖區非滿,可以放數據了*/
pthread_cond_signal(&b->notfull);
//對互斥信號量進行解鎖
pthread_mutex_unlock(&b->lock);
returndata;
}