C++11 producer Consumers

Source: Internet
Author: User

Here is a producer consumer question to introduce the use of condition_variable. When shared data between threads changes, it is possible to notify other threads through condition_variable. Consumers wait until the producer notifies them that the state has changed, condition_variable is used as follows:

• When a lock is held, the thread calls the wait

wait unlocks the held mutex (mutex), blocks this thread, and joins itself into the wake queue

• When notified (notification), the thread recovers from the block and joins the mutex queue (mutex queues)

After the thread is awakened, it continues to hold the lock run.

There are two types of Condition variable: condition_variable and Condition_variable_any, the previous one is more efficient, but the use is not flexible enough to support only STD::UNIQUE_LOCK<STD:: Mutex> type of mutex; the latter is more flexible and supports all types of locks, but is slightly less efficient.

One thing to note is that the thread that uses condition variable to communicate, condition variable needs to use the same mutex semaphore (mutex).

Here's an example: (Stop after you press ENTER)

#include <thread> #include <iostream> #include <mutex> #include <queue> #include <condition_ Variable> #include <atomic>using namespace Std;int main () {mutex lockbuffer;//Declaration of Mutex semaphore volatile bool Arretde Mande = false;           The end of the production and consumption process queue<long> buffer;        Condition_variable_any cndnotifierconsommateurs;//condition variable Condition_variable_any cndNotifierProducteur;        Thread Threadproducteur ([&] ()//producer Thread {std::atomic<long> interlock;//operation on interlock will be atomic           interlock=1;                               while (true) {std::this_thread::sleep_for (Chrono::milliseconds (15));                Long Element=interlock.fetch_add (1);//"1" lockbuffer.lock (); while (Buffer.size () ==10 && Arretdemande ==false) {Cndnotifie Rproducteur.wait (LockBuffer);//"2"} if (Arretdemande==true) {lockbuffer.unlock ();                Cndnotifierconsommateurs.notify_one ();//"3" break;                } buffer.push (Element);                cout << "Production unlement:" << element << "size:" << buffer.size () << Endl;                Lockbuffer.unlock ();        Cndnotifierconsommateurs.notify_one (); }    } );
Thread Threadconsommateur ([&] () {while (true) {Lockbuffe R.lock (); while (Buffer.empty () && arretdemande==false) {Cndnotifierco Nsommateurs.wait (LockBuffer); } if (Arretdemande==true && buffer.empty ()) {Lockbuffer.unlock ( ); Cndnotifierproducteur.notify_one (); Break } long Element=buffer.front (); Buffer.pop (); cout << "consommation element:" << element << "size:" << buffer.size () << Endl; Lockbuffer.unlock (); Cndnotifierproducteur.notify_one (); } } ); Std::cout << "pour arreter pressez [Entrez]" << Std::endl; GetChar (); Std::cout << "Arret demande" << endL Arretdemande=true; Threadproducteur.join (); Threadconsommateur.join (); cout<< "Main Thread" <<endl; return 0;}

Operation Result:

To illustrate the program, there are three threads in the program, the main thread, the producer thread, the consumer thread, the three threads are executed in a disorderly order, and the order of execution is controlled by some global variables. The function of the main thread is to control whether the production and consumption process is finished, when the program is running, the main thread receives an input via GetChar (), and when the input is received, the Arretdemande is set to true, and the other two threads terminate. The producer thread will produce the data in a queue type buffer, and unlock, notify the consumption of the thread, buffer up to "can" save 10 data, if there are already 10 data in buffer has not been taken away, will inform the consumer thread "consumption", If the Arretdmande is set, the lock is opened and the consuming thread is notified. The consumer thread mainly takes out the data in buffer, blocks itself when buffer is empty, notifies the producer thread when the Arretdemande is set, and the product is consumed, unlocks and notifies the producer thread. It is important to note that the two threads of the producer and consumer who need communication are communicating through condition variable, must operate the same mutex, this is LockBuffer, and each notify will open the current lock.

The operation of the interlock in the program is Atomic, Interlock.fet_add (n), the effect is to add interlock N, and then return the value of interlock before the addition of N, atomic type is through a certain sequence of memory rules to achieve this process.

Although conditon_variable can only support std::unique_lock<std::mutex> types of mutexes, it is sufficient in most cases and uses STD::UNIQUE_LOCK<STD:: Mutex> will be simpler because std::unique_lock<std::mutex> is initialized at the time of declaration and automatically unlocked after the end of the life cycle, so we don't have to spend too much time thinking about when to unlock. Let's take a look at the following procedure:

#include <condition_variable> #include <mutex> #include <thread> #include <iostream> #include    <queue> #include <chrono> int main () {std::queue<int> produced_nums;    Std::mutex m;;    Std::condition_variable Cond_var;    bool done = false;     BOOL notified = FALSE; Std::thread producer ([&] () {for (int i = 0; i < 5; ++i) {std::this_thread::sleep_for (Std::chro            No:: Seconds (1));  std:: Unique_lock<std::mutex > Lock (M);            May lock mutexes after construction, unlock before destruction.            Std::cout << "Producing" << i << ' \ n ';            Produced_nums.push (i); notified = TRUE;
Cond_var.notify_one (); } done = true; Cond_var.notify_one (); }); Cond_var.notify_one (); Std::thread consumer ([&] () {while (!done) {std:: Unique_lock<std::mutex > Lock (M); while (!notified) {//loop to avoid spurious wakeups cond_var.wait (lock); } while (!produced_nums.empty ()) {std::cout << "consuming" << Produced_nums.fron T () << ' \ n '; Produced_nums.pop (); } notified = FALSE; } }); Producer.join (); Consumer.join (); return 0;}

Operation Result:

C:\WINDOWS\SYSTEM32\CMD.EXE/C Producer_consumer.exe
Producing 0
Consuming 0
Producing 1
Consuming 1
Producing 2
Consuming 2
Producing 3
Consuming 3
Producing 4
Consuming 4
Hit any key to close the This window ...

Updated: August 4, 2012 16:53:25

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.