condition_variable是C++标准程序库中的一个头文件,定义了C++11标准中的一些表示线程的类、用于互斥访问的类与方法等。
一,成员函数:
1,Wait functions
wait
Wait until notified (public member function)
wait_for
Wait for timeout or until notified (public member function)
wait_until
Wait until notified or time point (public member function)
2,Notify functions
notify_one
Notify one (public member function)
notify_all
Notify all (public member function)
二,wait的两种用法:
1,只有一个lock形参
void wait( std::unique_lockstd::mutex& lock );
2,一个lock形参,一个lambda表达式,或者一个函数。
void wait( std::unique_lockstd::mutex& lock, Predicate pred );
三,唤醒方式:
两种wait都需要notify_one或者notify_all唤醒,但是第二种即使唤醒也满足表达式的条件,即:要返回true。
其中第二种wait的表达式至少要执行两次。
第一次是程序跑到wait时,第二次是收到notify时。
四,引申
wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,进入WAITTING状态。
但是此时的unique_lock和单独用unique_lock时区别还是挺大的。
单独使用unique_lock时,其他的线程要等待当前线程unlock。
配合wait时,只有执行表达式时才会触发mutex的lock,执行结束或者没有执行时,都处于unlock状态。
五,例子
#include <stdio.h>
#include <stdlib.h>
#include <mutex>
#include <chrono> // std::chrono::seconds
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <condition_variable>
std::condition_variable cv;
std::mutex my_lock;
std::mutex g_lock;
int g_variable = 0;
void thread_task2()
{
std::cout << "thread_task2 step1"<< std::endl;
g_lock.lock();
std::cout << "thread_task2 step2"<< std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "thread_task2 step3"<< std::endl;
std::lock_guard<std::mutex> lock(my_lock);
std::cout << "thread_task2 step4"<< std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "thread_task2 step5"<< std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "thread_task2 step6 "<< std::endl;
if(g_variable == 5)
{
std::cout << "thread_task2 step7 "<< std::endl;
g_variable = 100;
std::cout << "thread_task2 step8 "<< std::endl;
cv.notify_one();
}
g_lock.unlock();
}
bool istrue()
{
std::cout << "istrue step1"<< std::endl;
g_lock.lock();
std::cout << "istrue step2"<< std::endl;
g_lock.unlock();
std::cout << "istrue step3"<< std::endl;
return (g_variable == 100);
}
void thread_task3()
{
std::cout << "thread_task3 step1"<< std::endl;
g_variable = 5;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::unique_lock<std::mutex> lck(my_lock);
std::this_thread::sleep_for(std::chrono::seconds(5));
cv.wait(lck,istrue);
std::cout << "thread_task3 step2"<< std::endl;
}
int main(int argc, const char *argv[])
{
std::thread thread2 = std::thread(thread_task2);
std::thread thread3 = std::thread(thread_task3);
thread2.join();
thread3.join();
return EXIT_SUCCESS;
}