基於環形佇列的生產者消費者模型
阿新 • • 發佈:2019-01-13
之前的Blog基於Queue的生產者消費者模型,已經談過了基於queue的生產消費模型,其空間是可以動態分配的。而現在是基於固定大小的環形佇列重寫這個程式。
基於環形佇列的生產消費模型
- 環形佇列採用陣列模擬,用模運算來模擬環狀特性
- 環形結構起始狀態和結束狀態都是一樣的,不好判斷為空或者為滿,所以就需要通過計數器或者標記位來判斷滿或空。另外也可以預留一個空的位置,作為滿的狀態。
- 消費者總是跟在生產者的後邊,且不會超過生產者
- 生產者一直在消費者的前邊,且不會超過消費者一圈。
- head和tail指向同一個位置的時候,佇列為空。
- 當head在tail的下一個位置時,環形佇列為滿。
/*##### ringqueue.cc ####*/ #include"test.hpp" const int num=16; using namespace std; void *consume_routine(void *arg) { int d; RingQueue *q=(RingQueue*)arg; for(;;) { q->PopData(d); cout<<"consume done,data is..."<<d<<endl; } } void *product_routine(void *arg) { RingQueue *q=(RingQueue*)arg; srand((unsigned long)time(NULL)); for(;;) { int d=rand()%100+1; q->PushData(d); cout<<"Product done,data is..."<<d<<endl; sleep(1); } } int main() { RingQueue *q=new RingQueue(num); pthread_t c,p; pthread_create(&c,NULL,consume_routine,(void*)q); pthread_create(&p,NULL,product_routine,(void*)q); pthread_join(&c,NULL); pthread_join(&p,NULL); delete(q); return 0; }
/******* test.hpp *******/ #ifndef __TEST_HPP__ #define __TEST_HPP__ #include<vector> #include<iostream> #include<pthread.h> #include<unistd.h> #include<time.h> #include<semaphore.h> #include<stdlib.h> class RingQueue { private: std::vector<int> ring; int cap; sem_t blank_sem; sem_t data_sem; int c_step; //consume在圈中的位置 int p_step; //product在圈中的位置 private: void P(sem_t &sem) { sem_wait(&sem); } void V(sem_t &sem) { sem_post(&sem); } public: RingQueue(int cap_):cap(cap_),ring(cap_) { c_step=p_step=0; //初始時c_step和p_step在同一格 sem_init(&blank_sem,0,cap); //初始時需要寫入的輸入是整個圈的容量 sem_init(&data_sem,0,0); //初始時需要consume的值為0 } void PushData(const int& data) //進行資料生產 { P(blank_sem); ring[p_step]=data; //把資料放進去 V(data_sem); p_step++; p_step%=cap; //進行模運算來模擬環形特性 } void PopData(int &data ) { P(data_sem); //申請資料資源 data=ring[c_step]; //拿到資料 V(blank_sem); //空出格子 c_step++; c_step%=cap; } ~RingQueue() { sem_destroy(&blank_sem); sem_destroy(&data_sem); } }; #endif
****** makefile ******
ringqueue:ringqueue
.cc
g++ -o [email protected] $^ -lpthread -fpermissive
.PHONY:clean
clean:
rm -f ringqueue