【小记】C++ 标准库 std::condition_variable
std::condition_variable 和 std::condition_variable_any 是标准库线程同步以条件变量方式的实现。
它的作用是根据设定的条件同步一个或多个线程。
头文件:
#include <condition_variable>
其中 std::condition_variable 仅支持 std::unique_lock<std::mutex> 类型作为互斥量。
std::condition_variable_any 可以支持任意基本可锁定(BasicLockable)类型作为互斥量,例如 [C++14]std::shared_lock,但也就意味着它的效率低于前者。
它们两个的公共函数接口也基本一致:
名称 | 作用 | 支持 |
wait | 阻止。 | CV and Any |
wait_for | 阻止到时间间隔。 | CV and Any |
wait_until | 阻止到指定时间。 | CV and Any |
notify_one | 放行一个线程,如果此时托管了多个线程,则随机抽取。 | CV and Any |
notify_all | 放行所有线程。 | CV and Any |
native_handle | 返回原生句柄。 | CV |
它的语法是:
【伪代码】 // 负责同步阻塞的互斥量 std::mutex cv_mutex; // 声明 std::condition_variable cv; // 条件等待 收到通知且满足条件情况下放行 std::unique_lock<std::mutex> uni_m(cv_mutex); cv.wait(uni_m, [=] { return !flag; }); // 通知一个线程 cv.notify_one(); // 通知所有线程 cv.cv.notify_all();
例子演示了 std::condition_variable 的使用:
#include <iostream> using std::cout; using std::endl; #include <thread> #include <mutex> #include <condition_variable> void PrintID_CV(std::mutex& mu, std::condition_variable& cv, const int& flag) { std::unique_lock<std::mutex> uni_m(mu); cv.wait(uni_m, [=] { return flag != 1; }); cout << "Thread ID: " << std::this_thread::get_id() << endl; return; } int main() { std::mutex cv_mutex; std::condition_variable cv; int flag = 0; std::thread t1(&PrintID_CV, ref(cv_mutex), ref(cv), flag); while (flag != 1) { std::unique_lock<std::mutex> uni_m(cv_mutex); std::cout << "Input 1 is print thread id." << endl; std::cin >> flag; } cout << "Msg Thread..." << endl; cv.notify_one(); t1.join(); return EXIT_SUCCESS; }
以上例子运行后需要手动在键盘上输入 1 才会打印线程ID。
注意事项:
1,std::condition_variable 和 std::condition_variable_any 对象本身均不可拷贝和赋值。
2,根据代码演示,使用 std::std::condition_variable 与 std::condition_variable_any 都仅仅是负责条件变量,而加锁、解锁操作都始终需要有一个互斥量交由其托管。其中 std::condition_variable 仅支持 std::unique_lock<std::mutex>。
3,调用 wait()、wait_for()、wait_until() 函数后,内部会阻止当前线程运行,并 unlock 互斥量。
4,wait()、wait_for()、wait_until() 函数的第二个可选参数为返回 true 或 false 的任何表达式(lambda、Callback),为阻塞条件,当收到解锁信号且阻塞条件不满足(即表达式返回值为False)的情况下才会放行。
5,condition_variable.h 提供了额外的辅助函数 std::notify_all_at_thread_exit,语法为:
void std::notify_all_at_thread_exit (condition_variable& cv, unique_lock<mutex> mutex);
当调用该函数的线程退出后,会通知其他受该 std::condition_variable 托管的线程放行。为了避免误操作,请尽量避免使用该函数或在 wait 函数当中增加第二参数作为条件。
版权声明:
作者:芯片烤电池
链接:https://www.airchip.org.cn/index.php/2022/03/21/example-cpp-std-condition-variable/
来源:芯片烤电池
文章版权归作者所有,未经允许请勿转载。