【小记】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/
来源:芯片烤电池
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
【小记】C++ 标准库 std::condition_variable
  std::condition_variable 和 std::condition_variable_any 是标准库线程同步以条件变量方式的实现。 它的作用是根据设定的条件……
<<上一篇
下一篇>>