Producer and Consumer Model
One place, two roles, three relationships
A place is a buffer
Two roles refer to producers and consumers
Three relationships refer to:
Mutual exclusion between producers and producers
Mutual exclusion between consumers and consumers
Synchronization and Mutual Exclusion between Producers and Consumers
Advantages of the producer-consumer model:
1. Decoupling: that is, no direct data interaction is required
2. Supporting concurrency: that is, multiple threads can operate in the same place at the same time
3. Support uneven busyness and leisure
All three advantages are provided through this site, but because multiple roles may operate the site at the same time, it is necessary to ensure the safe operation of the site.
Using Blocking Queue + Conditional Variables to Simulate the Implementation of Producer-Consumer Model
#include <iostream> #include <queue> #include <pthread.h> #define MAX_QUEUE 10 class BlockQueue { private: std::queue<int> _queue; int _capacity;//Queue is growing dynamically and needs to limit the maximum number of nodes in the queue pthread_mutex_t _mutex; pthread_cond_t _cond_product; pthread_cond_t _cond_consumer; public: //Initialization BlockQueue(int cap = MAX_QUEUE):_capacity(cap) { pthread_mutex_init(&_mutex, NULL); pthread_cond_init(&_cond_product, NULL); pthread_cond_init(&_cond_consumer, NULL); } ~BlockQueue() { pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cond_product); pthread_cond_destroy(&_cond_consumer); } //Producers in the queue bool QueuePush(int data) { pthread_mutex_lock(&_mutex); while(_queue.size() == _capacity) //The queue is full, the producer waits { pthread_cond_wait(&_cond_product, &_mutex); } _queue.push(data); pthread_cond_signal(&_cond_consumer); pthread_mutex_unlock(&_mutex); } //Consumers out of the queue bool QueuePop(int &data) { pthread_mutex_lock(&_mutex); while(_queue.empty()) //Queue empty, consumer waiting { pthread_cond_wait(&_cond_consumer, &_mutex); } data = _queue.front();//Get the first node of the team _queue.pop(); pthread_cond_signal(&_cond_product); pthread_mutex_unlock(&_mutex); } }; //Producer entry function void *thr_product (void *arg) { BlockQueue *q = (BlockQueue*)arg; int i = 0; while(1) { q->QueuePush(i++);//Put data in std::cout<<"productor:"<<pthread_self()<<"put data:" << i<<"\n"; } return NULL; } //Consumer entry function void *thr_consumer (void *arg) { BlockQueue *q = (BlockQueue*)arg;//Get parameters while(1) { int data; q->QueuePop(data);//Get the data out std::cout<<"consumer:"<<pthread_self()<<"get data:"<<data<<"\n"; } return NULL; } int main() { pthread_t con_tid[4], pro_tid[4]; BlockQueue q; int ret; //Create four producer threads and four consumer threads, respectively for (int i = 0; i < 4; i++) { ret = pthread_create(&con_tid[i], NULL, thr_consumer,(void*)&q); if (ret != 0) { std::cout<<"thread create error\n"; return -1; } } for (int i = 0; i < 4; i++) { ret = pthread_create(&pro_tid[i], NULL, thr_product, (void*)&q); if (ret != 0) { std::cout<<"thread create error\n"; return -1; } } //To prevent threads from exiting directly, wait here for (int i = 0; i < 4; i++) { pthread_join(con_tid[i], NULL); } for (int i = 0; i < 4; i++) { pthread_join(pro_tid[i], NULL); } return 0; }