"Go" c++11 Concurrency Guide V (std::condition_variable detailed)

Source: Internet
Author: User

Http://www.cnblogs.com/haippy/p/3252041.html

The previous three talk about "c++11 Concurrency Guide II (Std::thread detailed)", "C++11 Concurrency Guide Three (Std::mutex detailed)" respectively introduced the Std::thread,std::mutex,std::future and other related content, I believe readers on c+ +11 multithreaded programming has a basic understanding, this article will introduce the C++11 standard in the <condition_variable> header file inside the class and related functions.

<condition_variable > Header files mainly contain classes and functions related to conditional variables. The related classes include std::condition_variable and Std::condition_variable_any, as well as enumeration type Std::cv_status. Also includes the function std::notify_all_at_thread_exit (), the following describes the above several types respectively.

Std::condition_variable Class Introduction

Std::condition_variable is a conditional variable, and more on the definition of a condition variable refer to Wikipedia. Linux uses the pthread_cond_* () function in the Pthread library to provide functionality related to condition variables, and Windows references MSDN.

When a wait function of an Std::condition_variable object is called, it uses Std::unique_lock (via Std::mutex) to lock the current thread. The current thread is blocked until another thread invokes the notification function on the same Std::condition_variable object to wake the current thread.

Std::condition_variable objects typically use std::unique_lock<std::mutex> to wait, and if you need to use a different lockable type, you can use Std::condition_ Variable_any class, the use of Std::condition_variable_any is described later in this article.

First, let's look at a simple example

#include <iostream>//std::cout#include <thread>//Std::thread#include <mut ex>//Std::mutex, Std::unique_lock#include <condition_variable>//STD::CONDITION_VARIABLESTD: : Mutex MTX; Global mutex. std::condition_variable CV; Global condition variable. BOOL ready = false;    Global flag bit. void do_print_id (int id) {std::unique_lock <std::mutex> lck (MTX); while (!ready)//If the flag bit is not true, wait for ... cv.wait (LCK);    The current thread is blocked, and when the global flag bit becomes true, the//thread is woken up and continues to execute the print thread number ID. Std::cout << "thread" << ID << ' \ n ';}    void Go () {std::unique_lock <std::mutex> lck (MTX); Ready = true;    Sets the global flag bit to true. Cv.notify_all (); Wakes all threads.}    int main () {std::thread threads[10];    Spawn threads:for (int i = 0; i < ten; ++i) threads[i] = Std::thread (do_print_id, i);    Std::cout << "Threads ready to race...\n"; Go ();  Go!    For (Auto & th:threads) Th.join (); return 0;}

The results of the implementation are as follows:

concurrency)./conditionvariable-basic1 threads ready to Race...thread 1thread 0thread 2thread 3thread 4thread 5thread 6thread 7thread 8thread 9

Well, after having a basic understanding of the condition variables, let's look at the various member functions of std::condition_variable.

Std::condition_variable constructor function

Default (1)
Condition_variable ();
copy [deleted] (2)
Condition_variable (const condition_variable&) = delete;

The copy constructor for std::condition_variable is disabled, and only the default constructor is provided.

Std::condition_variable::wait () Introduction

Unconditional (1)
void Wait (unique_lock<mutex>& lck);
Predicate (2)
Template <class predicate>  void Wait (unique_lock<mutex>& lck, predicate pred);

Std::condition_variable provides two kinds of wait () functions. When the current thread calls wait (), it will be blocked (the current thread should have acquired a lock (mutex), and it may be lck) until another thread calls Notify_* to wake up the current thread.

When the thread is blocked, the function is automatically called lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。 in addition, once the thread is notified (notified, which is usually called by some other notify_* to wake up the current threads), the wait () function is also automatically called Lck.lock (), making the state of lck and the wait function is the same as when it is invoked.

In the second case (that is, predicate is set), calling Wait () only when the pred condition is false will block the current thread and will be unblocked only if pred is true when the notification is received by another thread. So the second case is similar to the following code:

while (!pred ()) wait (LCK);

Take a look at the following example (reference):

 #include <iostream>//std::cout#include <thread>//Std::thread, Std::this    _thread::yield#include <mutex>//Std::mutex, Std::unique_lock#include <condition_variable> Std::condition_variablestd::mutex mtx;std::condition_variable Cv;int cargo = 0;bool shipment_available () {return car Go! = 0;}        Consumer thread. void consume (int n) {for (int i = 0; i < n; ++i) {Std::unique_lock <std::mutex> lck (MTX);        Cv.wait (Lck, shipment_available);        Std::cout << cargo << ' \ n ';    Cargo = 0;    }}int Main () {Std::thread consumer_thread (consume, 10);//Consumer thread.    The main thread is producer threads, producing 10 items.        for (int i = 0; i < ten; ++i) {while (shipment_available ()) Std::this_thread::yield ();        Std::unique_lock <std::mutex> lck (MTX);        Cargo = i + 1;    Cv.notify_one ();    } consumer_thread.join (); return 0;} 

The results of the program execution are as follows:

concurrency)./conditionvariable-wait 12345678910

Std::condition_variable::wait_for () Introduction

Unconditional (1)
Template <class Rep, class period>  cv_status wait_for (unique_lock<mutex>& lck,                      const chrono:: duration<rep,period>& rel_time);
Predicate (2)
Template <class Rep, class Period, class predicate>       bool Wait_for (unique_lock<mutex>& lck,                      Const Chrono::d uration<rep,period>& rel_time, predicate pred);

Similar to std::condition_variable::wait () , but wait_for can specify a time period that will be blocked until the current thread receives a notification or the specified time Rel_time times out. Once it has timed out or received notifications from other threads, Wait_for returns, and the remaining processing steps are similar to wait ().

In addition, the last parameter of the overloaded version of Wait_for (predicte (2)) pred represents the predictive condition of wait_for, and calling Wait () only when the pred condition is false will block the current thread and receive notifications from other threads Only when Pred is true will it be unblocked, so it is equivalent to the following code:

Return Wait_until (Lck, Chrono::steady_clock::now () + Rel_time, Std::move (pred));

Take a look at the following example (reference), in the following example, the main thread waits for the th thread to enter a value and then prints the value received by the th thread from the terminal, and the main thread waits until the value is accepted by the th thread, one time per second, and prints a "." :

#include <iostream>           //Std::cout#include <thread>             //Std::thread#include <chrono>             // Std::chrono::seconds#include <mutex>              //Std::mutex, Std::unique_lock#include <condition_variable>/ /std::condition_variable, std::cv_statusstd::condition_variable cv;int value;void do_read_value () {    std::cin >> value;    Cv.notify_one ();} int main () {    std::cout << ", enter an integer (I'll be printing dots): \ n";    Std::thread th (do_read_value);    Std::mutex MTX;    Std::unique_lock<std::mutex> lck (MTX);    while (Cv.wait_for (Lck,std::chrono::seconds (1)) = = Std::cv_status::timeout) {        std::cout << '. Std::cout.flush ();    }    Std::cout << "you entered:" << value << ' \ n ';    Th.join ();    return 0;}

Std::condition_variable::wait_until Introduction

Unconditional (1)
Template <class Clock, class duration>  cv_status wait_until (unique_lock<mutex>& lck,                        const chrono::time_point<clock,duration>& abs_time);
Predicate (2)
Template <class Clock, class Duration, class predicate>       bool Wait_until (unique_lock<mutex>& lck,< C6/>const chrono::time_point<clock,duration>& abs_time,                        predicate pred);

Similar to std::condition_variable::wait_for , but Wait_until can specify a point in time that the thread will be blocked until the current thread receives a notification or a specified point-in-time abs_time times out. And once the timeout is received or the other thread is notified, WAIT_UNTIL returns, and the remaining processing steps are similar to Wait_until ().

In addition, the last parameter of the overloaded version of Wait_until (predicte (2)) pred represents the predictive condition of wait_until, and calling Wait () only when the pred condition is false will block the current thread and receive additional lines Only when Pred is true will it be unblocked and therefore equivalent to the following code:

while (!pred ())  if (wait_until (lck,abs_time) = = cv_status::timeout)    return pred (); return true;

Std::condition_variable::notify_one () Introduction

Wakes up a waiting (wait) thread. If there is currently no waiting thread, the function does nothing, and if there are multiple waiting threads at the same time, waking a thread is indeterminate (unspecified).

Take a look at the following example (reference):

 #include <iostream>//std::cout#include <thread>//Std::thread#include &L t;mutex>//Std::mutex, Std::unique_lock#include <condition_variable>//STD::CONDITION_VARIABL Estd::mutex mtx;std::condition_variable Cv;int cargo = 0;    Shared value by producers and consumersvoid consumer () {Std::unique_lock < Std::mutex > lck (MTX);    while (cargo = = 0) cv.wait (LCK);    Std::cout << cargo << ' \ n '; Cargo = 0;}    void producer (int id) {Std::unique_lock < Std::mutex > lck (MTX);    cargo = ID; Cv.notify_one ();}    int main () {Std::thread consumers[10], producers[10];        Spawn consumers and producers:for (int i = 0; i <; ++i) {Consumers[i] = std::thread (consumer);    Producers[i] = Std::thread (producer, i + 1);        }//join them back:for (int i = 0; i < ten; ++i) {producers[i].join ();    Consumers[i].join (); } return 0;} 

Std::condition_variable::notify_all () Introduction

Wakes up all wait threads. If there is currently no waiting thread, the function does nothing. Take a look at the following example:

#include <iostream>//std::cout#include <thread>//Std::thread#include <mut ex>//Std::mutex, Std::unique_lock#include <condition_variable>//STD::CONDITION_VARIABLESTD: : Mutex MTX; Global mutex. std::condition_variable CV; Global condition variable. BOOL ready = false;    Global flag bit. void do_print_id (int id) {std::unique_lock <std::mutex> lck (MTX); while (!ready)//If the flag bit is not true, wait for ... cv.wait (LCK);    The current thread is blocked, and when the global flag bit becomes true, the//thread is woken up and continues to execute the print thread number ID. Std::cout << "thread" << ID << ' \ n ';}    void Go () {std::unique_lock <std::mutex> lck (MTX); Ready = true;    Sets the global flag bit to true. Cv.notify_all (); Wakes all threads.}    int main () {std::thread threads[10];    Spawn threads:for (int i = 0; i < ten; ++i) threads[i] = Std::thread (do_print_id, i);    Std::cout << "Threads ready to race...\n"; Go ();  Go!    For (Auto & th:threads) Th.join (); return 0;}
Std::condition_variable_any Introduction

With std::condition_variable 类似,只不过 std::condition_variable_any 的 wait 函数可以接受任何 lockable 参数,而 std::condition_variable 只能接受 std::unique_lock<std::mutex> 类型的参数,除此以外,和 std::condition_variable 几乎完全一样。

Std::cv_status Enumeration Type Description
cv_status::no_timeout Wait_for or Wait_until did not time out, that is, within the specified time period of the internal process received notification.
cv_status::timeout Wait_for or Wait_until timeout.
Std::notify_all_at_thread_exit

The function prototypes are:

void Notify_all_at_thread_exit (condition_variable& cond, unique_lock<mutex> lck);

When the thread that invokes the function exits, all cond threads waiting on the condition variable receive a notification. Take a look at the following example (reference):

#include <iostream>           //Std::cout#include <thread>             //Std::thread#include <mutex>              // Std::mutex, Std::unique_lock#include <condition_variable>//Std::condition_variablestd::mutex MTX;STD:: Condition_variable Cv;bool ready = false;void print_id (int id) {  std::unique_lock<std::mutex> lck (MTX);  while (!ready) cv.wait (LCK);  // ...  Std::cout << "thread" << ID << ' \ n ';} void Go () {  std::unique_lock<std::mutex> lck (MTX);  Std::notify_all_at_thread_exit (Cv,std::move (LCK));  Ready = true;} int main () {  std::thread threads[10];  Spawn Threads: for  (int i=0; i<10; ++i)    threads[i] = Std::thread (print_id,i);  Std::cout << "Threads ready to race...\n";  Std::thread (GO). Detach ();   Go!  for (auto& th:threads) th.join ();  return 0;}

All right, that's it.,<condition_variable> two conditional variable classes (std::condition_variable and Std::condition_variable_any) in the header file, enumeration type (std:: Cv_status), as well as auxiliary functions (Std::notify_all_at_thread_exit ()) have been introduced. Starting from the next chapter I will gradually begin to introduce the contents of the <atomic> header file, the following article will also introduce C++11 memory model, involving a slightly lower level, I hope you can maintain interest, learning c++11 concurrent programming, if you find the error in this article, please give me feedback ;-)。

"Go" c++11 Concurrency Guide V (std::condition_variable detailed)

Related Article

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.