C ++ 11 concurrent programming-condition_variable

Source: Internet
Author: User

C ++ 11 concurrent programming-condition_variable

The header file mainly contains classes and functions related to condition variables. Related classes includestd::condition_variableAndstd::condition_variable_anyAnd the enumerated type.std::cv_status. Functions are also included.std::notify_all_at_thread_exit()The following describes the above types.

Std: condition_variable class Introduction

std::condition_variableIs a condition variable. For more definitions of condition variables, see Wikipedia.LinuxUsePthreadLibrarypthread_cond_*()Functions provide functions related to conditional variables,WindowsFor more information, seeMSDN.

Whenstd::condition_variableAn objectwaitWhen a function is called, it usesstd::unique_lock(Passstd::mutex) To lock the current thread. The current thread will be blocked until another thread is in the samestd::condition_variableObject callednotificationFunction to wake up the current thread.

std::condition_variableObjects usually usestd::unique_lock To wait, if you need to use anotherlockableType, which can be usedstd::condition_variable_anyClass, which will be discussed later in this articlestd::condition_variable_any.

# Include
  
   
// Std: cout # include
   
    
// Std: thread # include
    
     
// Std: mutex, std: unique_lock # include
     
      
// Std: condition_variablestd: mutex CTX; // global mutex lock. std: condition_variable cv; // global condition variable. bool ready = false; // global flag. void do_print_id (int id) {std: unique_lock
      
        Lck (CTX); while (! Ready) // if the flag bit is not true, wait... cv. wait (lck); // The current thread is blocked. When the global flag bit is set to true, // The thread is awakened and the print thread id continues. std: cout <"thread" <id <'\ n';} void go () {std: unique_lock
       
         Lck (CTX); ready = true; // you can specify true as the global flag. cv. notify_all (); // wake up all threads .} int main () {std: thread threads [10]; // spawn 10 threads: for (int I = 0; I <10; ++ I) threads [I] = std: thread (do_print_id, I); std: cout <"10 threads ready to race... \ n "; go (); // go! For (auto & th: threads) th. join (); return 0 ;}
       
      
     
    
   
  

Result:

10 threads ready to race...thread 1thread 0thread 2thread 3thread 4thread 5thread 6thread 7thread 8thread 9

Well, after having a basic understanding of conditional variables, let's take a look.std::condition_variable.

std::condition_variableOnly the default constructor is provided.

std::condition_variable::wait()Introduction:
void wait (unique_lock
  
   & lck);template 
   
      void wait (unique_lock
    
     & lck, Predicate pred);
    
   
  

std::condition_variableProvides two typeswait()Function. Current thread callwait()Then it will be blocked (the current thread should get the lock (mutex).lck) Until another thread callsnotify_*The current thread is awakened.

This function is automatically called when the thread is blocked.lck.unlock()Release the lock so that other threads blocked in lock competition can continue to execute. In addition, once the current thread gets a notification (notified, Usually called by another threadnotify_*Wake up the current thread ),wait()The function is also called automatically.lck.lock(), MakinglckStatus andwaitFunctions are the same when called.

In the second case (that is,Predicate), Only whenpredThe condition isfalseTime callwait()Will block the current thread, and only whenpredIstrueWill be removed. The second case is similar to the following code:

while (!pred()) wait(lck);
# Include
  
   
// Std: cout # include
   
    
// Std: thread, std: this_thread: yield # include
    
     
// Std: mutex, std: unique_lock # include
     
      
// Std: condition_variablestd: mutex CTX; std: condition_variable cv; int cargo = 0; bool shipment_available () {return cargo! = 0;} // consumer thread. void consume (int n) {for (int I = 0; I <n ;++ I) {std: unique_lock
      
        Lck (CTX); 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 the producer thread, producing 10 items. for (int I = 0; I <10; ++ I) {while (shipment_available () std: this_thread: yield (); std: unique_lock
       
         Lck (CTX); cargo = I + 1; cv. policy_one () ;}consumer_thread.join (); return 0 ;}
       
      
     
    
   
  
12345678910
Std: condition_variable: wait_for ()
template 
  
     cv_status wait_for (unique_lock
   
    & lck,                      const chrono::duration
    
     & rel_time);template 
     
             bool wait_for (unique_lock
      
       & lck, const chrono::duration
       
        & rel_time, Predicate pred);
       
      
     
    
   
  

Andstd::condition_variable::wait()Similar,wait_forYou can specify a time period when the current thread receives a notification or the specified time.rel_timeBefore timeout, the thread will be in the blocking status. Once timeout or other threads are notified,wait_forReturn, the remaining processing steps andwait()Similar.

In addition,wait_forThe last parameter of the overloaded version.predIndicateswait_forOnly whenpredThe condition isfalseTime callwait()Will block the current thread, and only whenpredIstrueWill be removed, so it is equivalent to the following code:

return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred));

Please refer to the following example (reference). In the following example, the main thread waitsthThe thread inputs a value and thenthThe value received by the thread from the terminal is printed inthBefore the thread receives the value, the main thread waits until every second times out and prints".":

#include 
  
              // std::cout#include 
   
                 // std::thread#include 
    
                  // std::chrono::seconds#include 
     
                    // std::mutex, std::unique_lock#include 
      
        // 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 << "Please, enter an integer (I'll be printing dots): \n"; std::thread th(do_read_value); std::mutex mtx; std::unique_lock
       
         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
template 
  
     cv_status wait_until (unique_lock
   
    & lck,                        const chrono::time_point
    
     & abs_time);template 
     
             bool wait_until (unique_lock
      
       & lck, const chrono::time_point
       
        & abs_time, Predicate pred);
       
      
     
    
   
  

Andstd::condition_variable::wait_forSimilar,wait_untilYou can specify a time point when the current thread receives a notification or a specified time point.abs_timeBefore timeout, the thread will be in the blocking status. Once timeout or other threads are notified,wait_untilReturn, the remaining processing steps andwait_until()Similar.

In addition,wait_untilThe last parameter of the overloaded version.predIndicateswait_untilOnly whenpredThe condition isfalseTime callwait()Will block the current thread, and only whenpredIstrueWill be removed, so it is equivalent to the following code:

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

Wake up a wait (wait) Thread. If no waiting thread exists, the function does not do anything. If multiple waiting threads exist at the same time, it is uncertain to wake up a thread.(unspecified).

See the following example (reference ):

#include 
  
                   // std::cout#include 
   
                    // std::thread#include 
    
                     // std::mutex, std::unique_lock#include 
     
          // std::condition_variablestd::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 10 consumers and 10 producers:    for (int i = 0; i < 10; ++i) {        consumers[i] = std::thread(consumer);        producers[i] = std::thread(producer, i + 1);    }    // join them back:    for (int i = 0; i < 10; ++i) {        producers[i].join();        consumers[i].join();    }    return 0;}
     
    
   
  
Std: condition_variable: policy_all ()

Wake up all waits(wait)Thread. If there is no waiting thread, this function does not do anything. See the following example:

# Include
  
   
// Std: cout # include
   
    
// Std: thread # include
    
     
// Std: mutex, std: unique_lock # include
     
      
// Std: condition_variablestd: mutex CTX; // global mutex lock. std: condition_variable cv; // global condition variable. bool ready = false; // global flag. void do_print_id (int id) {std: unique_lock
      
        Lck (CTX); while (! Ready) // if the flag bit is not true, wait... cv. wait (lck); // The current thread is blocked. When the global flag bit is set to true, // The thread is awakened and the print thread id continues. std: cout <"thread" <id <'\ n';} void go () {std: unique_lock
       
         Lck (CTX); ready = true; // you can specify true as the global flag. cv. notify_all (); // wake up all threads .} int main () {std: thread threads [10]; // spawn 10 threads: for (int I = 0; I <10; ++ I) threads [I] = std: thread (do_print_id, I); std: cout <"10 threads ready to race... \ n "; go (); // go! For (auto & th: threads) th. join (); return 0 ;}
       
      
     
    
   
  
Std: condition_variable_any Introduction

Andstd::condition_variableSimilar,std::condition_variable_anyOfwaitFunctions can accept anylockableParameters, whilestd::condition_variableOnly Acceptstd::unique_lock Parameter of the type, andstd::condition_variableAlmost identical.

std::cv_statusEnumeration type

cv_status::no_timeout wait_forOrwait_untilIf no timeout occurs, the thread receives a notification within the specified period.

Cv_status: timeout wait_for or wait_until timeout. Std: policy_all_at_thread_exit

Function prototype:

void notify_all_at_thread_exit (condition_variable& cond, unique_lock
  
    lck);
  

When the thread that calls this function exits, allcondThe waiting thread on the condition variable will receive a notification. See the following example (reference ):

#include 
  
              // std::cout#include 
   
                 // std::thread#include 
    
                   // std::mutex, std::unique_lock#include 
     
       // std::condition_variablestd::mutex mtx;std::condition_variable cv;bool ready = false;void print_id (int id) {  std::unique_lock
      
        lck(mtx); while (!ready) cv.wait(lck); // ... std::cout << "thread " << id << '\n';}void go() { std::unique_lock
       
         lck(mtx); std::notify_all_at_thread_exit(cv,std::move(lck)); ready = true;}int main (){ std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(print_id,i); std::cout << "10 threads ready to race...\n"; std::thread(go).detach(); // go! for (auto& th : threads) th.join(); return 0;}
       
      
     
    
   
  

Okay, so far, The two conditional variable classes in the header file (std::condition_variableAndstd::condition_variable_any), Enumeration type (std::cv_status) And auxiliary functions (std::notify_all_at_thread_exit().

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.