線程併發的生產者-消費者模型:併發
1.兩個進程對同一個內存資源進行操做,一個是生產者,一個是消費者。函數
2.生產者往共享內存資源填充數據,若是區域滿,則等待消費者消費數據。spa
3.消費者從共享內存資源取數據,若是區域空,則等待生產者填充數據。線程
4.生產者的填充數據行爲和消費者的消費數據行爲不可在同一時間發生。指針
下面用Windows的信號量以及線程等API模擬生產者-消費者模型code
#include <Windows.h> #include <stdio.h> #define N 100 #define TRUE 1 typedef int Semaphore; Semaphore full = 0, Empty = N; //共享資源區滿槽數目和空槽數目 int in = 0, out = 0; //緩衝區生產,消費數據指針 HANDLE mutex; int ProducerThread[5]; int ConsumerThread[5]; int Buffer[N+4]; //緩衝區 int produce_item() { //生產(隨機數) return (rand()%N + N)%N; } int insert_item(int item) { //插入資源 in %= N; printf("生產到緩衝區槽: %d\n",in); Buffer[in] = item; return Buffer[in++]; } int remove_item() { //移出資源 out %= N; printf(" 取走緩衝區槽 %d 的數\n",out); return Buffer[out++]; } int consume_item(int item) { //consume it } void down(HANDLE handle) { //wait / P WaitForSingleObject(handle, INFINITE); } void up(HANDLE handle) { //signal / V ReleaseSemaphore(handle, 1, NULL); } DWORD WINAPI producer(LPVOID v) { int item; while(TRUE) { item = produce_item(); if(Empty > 0) { //down(empty) Empty--; down(mutex); //down(mutex) insert_item(item); full++; //up(full) up(mutex); //up(mutex) } Sleep(2000); } return 1; } DWORD WINAPI consumer(LPVOID v) { int item; while(TRUE) { if(full > 0) { //down(full) full--; down(mutex); //down(mutex) item = remove_item(); consume_item(item); Empty++; //up(empty) up(mutex); //up(mutex) } Sleep(2000); } return 1; } int main() { DWORD Tid; mutex = CreateSemaphore( //建立互斥信號量mutex NULL, 1, 1, NULL ); for(int i=0;i<4;i++) { ProducerThread[i] = i+1; CreateThread( //建立生產者線程 NULL, //不能被子線程繼承 0, //默認堆棧大小 producer, //生產者函數 &ProducerThread[i], //傳參 0, //建立後當即執行 &Tid //線程ID ); ConsumerThread[i] = i+1; CreateThread(NULL,0,consumer,&ConsumerThread[i],0,&Tid); //建立消費者線程 } Sleep(20000); return 0; }
運行結果:blog
或者使用自定義的信號量mutex來實現:繼承
#include <Windows.h> #include <stdio.h> #define N 100 #define TRUE 1 typedef int Semaphore; Semaphore mutex = 1; //互斥信號量 Semaphore full = 0, Empty = N; //臨界區滿槽數目和空槽數目 int in = 0, out = 0; //緩衝區生產,消費數據指針 int ProducerThread[5]; int ConsumerThread[5]; int Buffer[N+4]; //緩衝區 int produce_item() { //生產隨機數 return (rand()%N + N)%N; } int insert_item(int item) { //插入臨界區 in %= N; printf("生產到緩衝區槽: %d\n",in); Buffer[in] = item; return Buffer[in++]; } int remove_item() { //移出臨界區 out %= N; printf(" 取走緩衝區槽 %d 的數\n",out); return Buffer[out++]; } int consume_item(int item) { //consume it } DWORD WINAPI producer(LPVOID v) { int item; while(TRUE) { item = produce_item(); //生產物品 Empty--; //P(Empty) if(Empty < 0) //沒有空槽能夠添加數據 Empty++; //還原Empty,繼續循環等待 else if(mutex > 0) { //不然若是mutex = 1,臨界區未被訪問 mutex--; //加鎖 insert_item(item); //往臨界區填入數據 full++; //滿槽數加1 mutex++; //釋放鎖 } Sleep(2000); } return 1; } DWORD WINAPI consumer(LPVOID v) { int item; while(TRUE) { full--; //P(full) if(full < 0) //若是沒有滿槽,沒法消費 full++; //還原full,繼續等待 else if(mutex > 0) { //不然若是mutex = 1,臨界區未被訪問 mutex--; //加鎖 item = remove_item(); //將數據移出臨界區 consume_item(item); //消費 Empty++; //空槽數目加1 mutex++; //釋放鎖 } Sleep(2000); } return 1; } int main() { DWORD Tid; for(int i=0;i<4;i++) { ProducerThread[i] = i+1; CreateThread(NULL,0,producer,0,0,&Tid); ConsumerThread[i] = i+1; CreateThread(NULL,0,consumer,0,0,&Tid); } Sleep(20000); return 0; }
也能達到效果:進程