条件变量用于等待特定条件下的线程唤醒,通常和互斥锁搭配使用。mutex 一般以抢占方式保护资源,但如果希望让某个线程先执行,再让另一个线程执行,就可以借助条件变量来协调。

在使用条件变量时,等待一方仍然必须持有 mutex。调用等待函数之前,线程要先锁定 mutex,再调用条件变量的等待方法;当等待函数返回时,mutex 会处于被阻塞的状态。当线程等待条件变为 true 的过程中,mutex 并没有被持续锁定。为了避免不可预知的结果,所有等待同一个条件变量的线程都必须使用同一个 mutex 对象。

condition_variable 与 condition_variable_any 的区别

类型 condition_variable_any 的对象可以搭配任意类型的 mutex 使用,对应的 mutex 类型也不要求必须提供 try_lock 方法。相比之下,类型 condition_variable 的对象只能与 unique_lock<mutex> 搭配使用;这一类型的对象通常比 condition_variable_any<unique_lock<mutex>> 的对象更快一些。

要等待某个事件,先锁定 mutex,再调用条件变量的 wait 方法。该调用会一直阻塞,直到另一个线程在同一个条件变量上触发通知为止。

虚假唤醒

当等待条件变量的线程在没有收到相应通知的情况下被取消时,就会出现所谓的"虚假"唤醒。为了识别这种情况,在等待函数返回之后,代码需要显式地再次检查条件是否真的为 true。通常的做法是把检查放在循环里;也可以使用 wait(unique_lock<mutex>& lock, Predicate pred) 这种带谓词的重载,由标准库自动帮你完成循环检查。

读线程等待写线程完成后被唤醒

.
                //读线程等待写线程完毕后 唤醒
                
                std::mutex _mutex;//全局互斥锁
                
                std::condition_variable_any condition;//全局条件变量
                
                int x = 1;//全局资源
                
                void func_1()//write thread
                {
                	Sleep(100);
                
                        {
                	    lock_guard<std::mutex> lock(_mutex);
                	    x += 1;
                        }
                	condition.notify_one(); //唤醒,等待写入而挂起的读线程
                
                }
                
                void func_2()//read thread
                {
                	unique_lock<std::mutex>lock(_mutex) ;
                
                	condition.wait(_mutex);//挂起该线程,等待修改完数据的线程唤醒,
                	cout << x << endl;
                
                }
                
                
                int main(int argc, char *argv[])
                {
                
                	auto t = std::thread(func_1);//写线程
                
                	t.detach();
                
                	auto t1 = std::thread(func_2);//读线程
                
                	t1.detach();
                
                	Sleep(300);
                
                	cout << x << endl;
                	cout << "main thread" << endl;
                
                
                
                	system("pause");
                	return 0;
                }

condition_variable 只能和 std::mutex 搭配使用,而 condition_variable_any 的适用范围更广。

几种不同的等待方式


                	std::thread t([&]
                	{
                		while (true)
                		{
                			while (1)
                			{
                				mm.lock();
                
                				con.wait(mm, [&](){return !_queue.empty(); });//被通知后,第二个参数返回值是true的时候
                                //  才会解除阻塞
                				cout << "getMsg" << endl;
                				mm.unlock();
                
                			}
                
                
                
                			while (_queue.empty())
                			{
                				mm.lock();
                				con.wait_for(mm,std::chrono::milliseconds(100));//固定时间的等待
                
                				cout << "getMsg" << endl;
                				mm.unlock();
                
                			}
                
                
                	        while (_queue.empty())
                			{
                				mm.lock();
                				con.wait_for(mm));//一直等待直到 被通知
                
                				cout << "getMsg" << endl;
                				mm.unlock();
                
                			}
                		}
                
                	});
                
                	t.detach();
                

MSDN 参考:https://msdn.microsoft.com/zh-cn/library/hh874761(v=vs.120).aspx