c++多线程之条件变量

1.条件变量condition_variable、wait()、notify_one()(通知一个线程)

1.1condition_variable实际上是一个类,是一个和条件相关的一个类,等待一个条件达成,这个类需要和互斥量来配合工作,用的时候我们要生成这个类的对象。

1.2.1wait()函数用于等待一个消息,他的第二个参数lambda表达式返回值是true,那wait()直接返回,否则wait()将解锁互斥量,并堵塞到本行,堵塞到其他某个线程调用notify_one()成员函数为止。如果wait()没有第二个参数,那么结果和lambda表达式返回false一样。

1.2.2当线程调用notify_one()唤醒wait()(原先堵塞状态)时,wait()恢复后,不断地尝试重新获取互斥量锁,如果获取不到,那么流程卡在wait这里等着获取,如果获取到了锁,那么就判断wait()是都有第二个参数,如果有,那么判断lambda表达式值的真假,如果为true,则wait返回,流程走下去(此时互斥锁被锁着),如果为false那么wait对互斥量解锁,继续睡眠堵塞状态。如果没有结果和true的结果是一致的。

注:notify_one的效果不一定能快速唤醒wait(),如果另外一个线程不是卡在wait处等待唤醒,在做其他事务是,唤醒是无效的。inMsgRecvQueue()与outMsgRecvQueue()调用的时候两个线程对锁的竞争,会出现inMsgRecvQueue()调用更多,导致插入的数据过多。通过lambda表达式判断取数据时是否有数据,可以避免虚假唤醒。

lambda表达式的使用参考https://www.cnblogs.com/DswCnblog/p/5629165.html

  1 #include                                                                
  2 #include                                                                  
  3 #include                                                                    
  4 #include                                                                   
  5 #include                                                      
  6                                                                                   
  7 using namespace std;                                                              
  8                                                                                   
  9 class A{                                                                          
 10 public:                                                                           
 11 //把收到的消息入到一个队列的线程                                                  
 12 void inMsgRecvQueue(){                                                            
 13     for(int i = 0;i < 100000; ++i){                                               
 14         cout<<"inMsgRecvQueue(_)执行,插入一个元素"< sbguard1(my_mutex1);                         
 16         msgRecvQueue.push_back(i);                                                
 17         my_cond.notify_one();  //通过调用该函数唤醒wait                           
 18     }                                                                             
 19     return;                                                                       
 20 }                                                                                 
 21                                                                                   
 22 //把数据从消息队列中取出的进程                                                    
 23   void outMsgRecvQueue(){                                                         
 24         int command = 0;                                                          
 25         while(true){                                                              
 26             std::unique_lock sbguard1(my_mutex1);                     
 27             my_cond.wait(sbguard1,[this]{                                         
 28                 if(!msgRecvQueue.empty())                                         
 29                     return true;                                                  
 30                 return false;                                                     
 31         });                                                                       
 23   void outMsgRecvQueue(){                                                         
 24         int command = 0;                                                          
 25         while(true){                                                              
 26             std::unique_lock sbguard1(my_mutex1);                     
 27             my_cond.wait(sbguard1,[this]{                                         
 28                 if(!msgRecvQueue.empty())                                         
 29                     return true;                                                  
 30                 return false;                                                     
 31         });                                                                       
 32         command = msgRecvQueue.front();                                           
 33         msgRecvQueue.pop_back();                                                  
 34         sbguard1.unlock();                                                                        
 35         cout<<"outMsgRecvQueue()执行,取出一个元素";                              
 36         }                                                                         
 37     }                                                                             
 38 private:                                                                          
 39     list msgRecvQueue;                                                       
 40     mutex my_mutex1;                                                              
 41     std::condition_variable  my_cond; //生成一个条件变量对象                      
 42 };  
 43 int main(){                                                                       
 44     A myobja;                                                                     
 45     thread myOutMsgobj(&A::outMsgRecvQueue,&myobja);                              
 46     thread myInMsgobj(&A::inMsgRecvQueue,&myobja);                                
 47     myInMsgobj.join();                                                            
 48     myOutMsgobj.join();                                                           
 49     return 0;                                                                     
 50 }                              

c++多线程之条件变量_第1张图片

2.notify_all()(同时唤醒多个线程)

  1 #include                                                                                
  2 #include                                                                  
  3 #include                                                                    
  4 #include                                                                   
  5 #include                                                      
  6                                                                                   
  7 using namespace std;                                                              
  8                                                                                   
  9 class A{                                                                          
 10 public:                                                                           
 11 //把收到的消息入到一个队列的线程                                                  
 12 void inMsgRecvQueue(){                                                            
 13     for(int i = 0;i < 100000; ++i){                                               
 14         std::unique_lock sbguard1(my_mutex1);                         
 15         cout<<"inMsgRecvQueue(_)执行,插入一个元素"< sbguard1(my_mutex1);                     
 27             my_cond.wait(sbguard1,[this]{                                         
 28                 if(!msgRecvQueue.empty())                                         
 29                     return true;                                                  
 30                 return false;                                                     
 31         });                                                                       
 32         command = msgRecvQueue.front();                                           
 33         msgRecvQueue.pop_back();                                                  
 34         cout<<"outMsgRecvQueue()执行,取出一个元素"< msgRecvQueue;                                                                                                       
 40     mutex my_mutex1;                                                              
 41     std::condition_variable  my_cond; //生成一个条件变量对象                      
 42 };                                                                                
 43 int main(){                                                                       
 44     A myobja;                                                                     
 45     thread myOutMsgobj(&A::outMsgRecvQueue,&myobja);                              
 46     thread myOutMsgobj2(&A::outMsgRecvQueue,&myobja);                             
 47     thread myInMsgobj(&A::inMsgRecvQueue,&myobja);                                
 48     myInMsgobj.join();                                                            
 49     myOutMsgobj.join();                                                           
 50     myOutMsgobj2.join();                                                          
 51     return 0;                                                                     
 52 }                   

c++多线程之条件变量_第2张图片

你可能感兴趣的:(c++,深入学习c++)