作業系統以及linux上都詳細地介紹了訊號量以及鎖的概念,其重要性可想而知,這事我寫的乙個比較簡單的多執行緒實現的生產者消費者模型,我會對裡面用到的函式等做出比較詳細的解釋,以方便解讀。
#include
#include
#include
#include
#include
#define producer 5 //生產者數目
#define consumer 5 //消費者數目
#define pool_size 11 //緩衝池大小
int pool[pool_size];
int head = 0; //第乙個產品的位置
int rear = 0; //最後乙個產品的位置
sem_t room_sem; //sem變數相當於,建立空餘位置的訊號量
sem_t product_sem; //商品數目的訊號量,和上面乙個一起配合同步
pthread_mutex_t mutex; //執行緒鎖,控制互斥
void *producer_fun() //生產者函式,注意他的返回型別
}void *consumer_fun() //消費者函式,不解釋了
}int main()
ret =sem_init(&product_sem,0,0); //初始化訊號,為0
if(ret!=0)
for(int i=0;i//建立生產者執行緒
}for(int i=0;i//建立消費者執行緒
}//釋放執行緒資源
for(int i=0;ifor(int i=0;i上面**除了我加的注釋的地方外,別的需要說明的函式就兩個
1、int pthread_create(pthread_t* tid, pthread_attr_t attr, void(start_routine)(void), void *arg);
tid:輸出引數,用於返回所建立執行緒的標識;
attr:用於設定執行緒屬性,大多數情況下傳null;
start_routine:用於指定執行緒主函式
arg:為執行緒主函式傳遞的引數
我們看下這個函式的最後兩個引數
void*(start_routine)(void):這個表示返回型別為void*,引數為void*的函式指標,如果城建的函式是其他型別,需要通過強制型別轉化。
void arg:這是個傳入的引數,但他最終不是傳給pthread_create()。而是傳給上面提到的那個繫結的void(start_routine)(void)。如果是其他型別的資料需要經過兩次轉化,如果需要多個引數可以通過結構體之類的資料結構包裝。
2、int pthread_join(pthread_t tid, void **retval);
tid: 被等待的執行緒的id;
retval:出參,用於接收被等待執行緒結束時的返回值。
很多人可能對第二個引數比較奇怪,第二個引數相當於返回值,是乙個出參,我們可以通過這個函式了解下:
int pthread_exit(void *retval);
retval: 執行緒結束時的返回值,用pthread_join可以獲取該值。
這就比較好理解了。
為什麼要**執行緒退出狀態呢,主要原因是linux有一種殭屍狀態,在乙個程序或者執行緒結束後,會有乙個結構體,儲存其退出是的狀態等資訊,只有在主線程**以後他才會消失,當然,這裡還有另外一種解決方式。
pthread_detach(pthread_self()) ;
他的作用是把該執行緒變為unjoinable,和主線程脫離關係,其在結束後會自動**資源。
有講的不對的地方希望指正,謝謝!!
生產者消費者模型
1.生產者消費者問題 producer consumer 有限緩衝,多執行緒同步。生產者執行緒和消費者執行緒共享固定大小緩衝區。2.關鍵是保證生產者不會再緩衝區滿時加入資料,消費者不會在緩衝區空時消耗資料。3.解決辦法 讓生產者在緩衝區滿時休眠,等下次消費者消耗緩衝區中的資料的時候,生產者才能被喚醒...
生產者消費者模型
生產者與消費者 3,2,1 三種關係 生產者與消費者 互斥,同步 消費者與消費者 互斥 生產者與生產者 互斥 條件變數 int pthread cond destroy pthread cond t cond int pthread cond init pthread cond t restrict...
生產者消費者模型
當佇列滿時,生產者需要等待佇列有空間才能繼續往裡面放入商品,而在等待的期間內,生產者必須釋放對臨界資源 即佇列 的占用權。因為生產者如果不釋放對臨界資源的占用權,那麼消費者就無法消費佇列中的商品,就不會讓佇列有空間,那麼生產者就會一直無限等待下去。因此,一般情況下,當佇列滿時,會讓生產者交出對臨界資...