The Producer-consumer producer-consumer model we are introducing here is a well-known design pattern in multithreaded design patterns. When it comes to producer-consumer problems, most people are not unfamiliar with the classic problem of OS class, and it is a common problem in computer programming. For its application, can cite countless examples, small to a multi-threaded procedure to the queue of shared mutex operation, large to the current popular middleware products, such as Bea Bmq (Bea Message Queue), IBM's MQ Serious and other middleware is the result of applying generalized system to the problem of producer consumer.
In fact, the producer consumer model is very similar to the PPL and C + + instances of our previous multithreaded design pattern guarded suspension pattern. In computer science, we describe producer consumer issues as:
A group of producers are producing messages and giving the message to consumers to consume. They have a buffer pool with n buffers in between, and the producer can put the produced messages into a buffer every time, and the consumer can take out the messages in one buffer at a time to consume. But this process has two conditions:
(1) When either party operates a buffer, it cannot operate on the buffer at the same time;
(2) Only if the buffer is free, the producer can produce it, and only if there is at least one product in the buffer, the consumer can take it out and consume it.
Here the two conditions correspond to mutual exclusion and synchronization.
It can be found that the producer consumer model is based on the guarded suspension model to make more restrictions, guarded suspension mode does not limit the capacity of the buffer, at any time can be added to the buffer of new messages, However, the producer-consumer model limits the capacity of the buffer, and when the buffer is full, it is not possible to add a message to it. Simply put, the Producer consumer mode is like adding a double guard and waiting for the guarded suspension mode, and its two protection is in contrast to the waiting conditions, we will modify the guarded suspension mode, The producer consumer model can be implemented.
ProducerConsumer.cpp: Defines the entry point of the console application.
using namespace Concurrency;
using namespace Std;
Class Request
{
Public
Request (unsigned int nID)
: M_nid (NID)
{
}
unsigned int GetID ()
{
return M_nid;
}
Private
unsigned int m_nid;
};
Request queue
The client adds the request into this queue
The server fetches requests from the client from this queue for processing
Class Requestqueue
{
Public
Gets the request and waits if the current request queue is empty
Request Getrequest ()
{
bool bwait = true;
while (bwait)
{
If there is no request in the buffer, wait for it.
Wait (500);
Cs.lock ();
bwait = m_queue.size () > 0? False:true;
Cs.unlock ();
}
Cs.lock ();
Request req = M_queue.front ();
M_queue.pop ();
Wait (1000);
cout<< "GET:" < Cs.unlock ();
return req;
}
To join the request in the request queue
void Setrequest (Request req)
{
BOOL bwait = false;
Do
{
Limit the size of the buffer, which is a protection that the producer consumer model adds more than guarded suspension mode
Cs.lock ();
bwait = M_queue.size () < 5? False:true;
if (bwait)
{
cout<< "Wait ..." < wait (500);
}
Cs.unlock ();
}
while (bwait);
Cs.lock ();
M_queue.push (req);
cout<< "SET:" < Cs.unlock ();
}
Private
Critical_section CS; To protect the critical section of the queue access
Queue M_queue;
};
int _tmain (int argc, _tchar* argv[])
{
Srand ((int) time (NULL));
Requestqueue queue;
Simulate multiple client requests, that is, the producer thread
Auto request = Make_task ([&] ()
{
int ncount = 0;
while (NCOUNT<20)
{
Wait (rand ()%10);
Queue.setrequest (Request (ncount));
++ncount;
}
});
The processing of the simulated client, i.e. the consumer thread
Auto Process = Make_task ([&] ()
{
while (true)
Queue.getrequest ();
});
Threads that execute requests and processes
task_group TG;
Tg.run (process);
Tg.run_and_wait (Request);
return 0;
}
In this example, the producer thread constantly generates a request to add a request to Requestqueue, when the request in Requestqueue is greater than 5 o'clock, waits, no longer adds a request to it, and the consumer thread keeps getting the request from the Requestqueue for processing. When there is no request in the queue, it waits. The producer consumer model is simple and effective, and is widely used.
Multithreaded design pattern: Producer-consumer Producer-Consumer mode C + +