欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > c/c++ >内容正文

c/c++

C++ std::condition_variable wait() wait_for() 区别

发布时间:2024/4/18 c/c++ 38 豆豆
生活随笔 收集整理的这篇文章主要介绍了 C++ std::condition_variable wait() wait_for() 区别 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

一、std::condition_variable 是条件变量。

wait()

当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

首先我们来看一个简单的例子

#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variablestd::mutex mtx; // 全局互斥锁. std::condition_variable cv; // 全局条件变量. bool ready = false; // 全局标志位.void do_print_id(int id) {std::unique_lock <std::mutex> lck(mtx);while (!ready) // 如果标志位不为 true, 则等待...cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,// 线程被唤醒, 继续往下执行打印线程编号id.std::cout << "thread " << id << '\n'; } void go() {std::unique_lock <std::mutex> lck(mtx);ready = true; // 设置全局标志位为 true.cv.notify_all(); // 唤醒所有线程. }int main() {std::thread threads[10]; // spawn 10 threads:for (int i = 0; i < 10; ++i)threads[i] = std::thread(do_print_id, i);std::cout << "10 threads ready to race...\n";go(); // go!for (auto & th:threads)th.join();return 0; }

执行结果如下:

10 threads ready to race... thread 1 thread 0 thread 2 thread 3 thread 4 thread 5 thread 6 thread 7 thread 8 thread 9

std::condition_variable::wait() 介绍

unconditional (1)predicate (2)
void wait (unique_lock<mutex>& lck);
  • template <class Predicate>

  • void wait (unique_lock<mutex>& lck, Predicate pred);在第二种情况下(即设置了 Predicate),只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。因此第二种情况类似以下代码:

  • 当前线程调用 wait() 后将被阻塞(此时当前线程应该获得了锁(mutex),不妨设获得锁 lck),直到另外某个线程调用 notify_* 唤醒了当前线程。

    在线程被阻塞时,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和 wait 函数被调用时相同。

    在第二种情况下(即设置了 Predicate),只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。

    因此第二种情况类似以下代码:

    while (!pred()) wait(lck);

    请看下面例子(参考):

    #include <iostream> // std::cout #include <thread> // std::thread, std::this_thread::yield #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variablestd::mutex mtx; std::condition_variable cv;int cargo = 0; bool shipment_available() {return cargo != 0; }// 消费者线程. void consume(int n) {for (int i = 0; i < n; ++i) {std::unique_lock <std::mutex> lck(mtx);cv.wait(lck, shipment_available);std::cout << cargo << '\n';cargo = 0;} } int main() {std::thread consumer_thread(consume, 10); // 消费者线程.// 主线程为生产者线程, 生产 10 个物品.for (int i = 0; i < 10; ++i) {while (shipment_available())std::this_thread::yield();std::unique_lock <std::mutex> lck(mtx);cargo = i + 1;cv.notify_one();}consumer_thread.join();return 0; }

    程序执行结果如下:

    concurrency ) ./ConditionVariable-wait 1 2 3 4 5 6 7 8 9 10

    wait_for()

    std::condition_variable::wait_for() 介绍

    unconditional (1)predicate (2)
  • template<class Rep, class Period>

  • cv_status wait_for(unique_lock<mutex>& lck, const chrono::duration<Rep,Period>& rel_time);

  • template<class Rep, class Period, class Predicate>

  • bool wait_for (unique_lock<mutex>& lck, const chrono::duration<Rep,Period>& rel_time, Predicate pred);

  • 与 std::condition_variable::wait() 类似,不过 wait_for 可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for 返回,剩下的处理步骤和 wait() 类似。

    另外,wait_for 的重载版本(predicte(2))的最后一个参数 pred 表示 wait_for 的预测条件,只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞,因此相当于如下代码:

    return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred));

    请看下面的例子(参考),下面的例子中,主线程等待 th 线程输入一个值,然后将 th 线程从终端接收的值打印出来,在 th 线程接受到值之前,主线程一直等待,每个一秒超时一次,并打印一个 ".":

    #include <iostream> // std::cout #include <thread> // std::thread #include <chrono> // std::chrono::seconds #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variable, std::cv_statusstd::condition_variable cv; int value;void do_read_value() {std::cin >> value;cv.notify_one(); }int main () {std::cout << "Please, enter an integer (I'll be printing dots): \n";std::thread th(do_read_value);std::mutex mtx;std::unique_lock<std::mutex> lck(mtx);while (cv.wait_for(lck,std::chrono::seconds(1)) == std::cv_status::timeout) {std::cout << '.';std::cout.flush();}std::cout << "You entered: " << value << '\n';th.join();return 0; }

    总结

    以上是生活随笔为你收集整理的C++ std::condition_variable wait() wait_for() 区别的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。