首页 > 编程语言 >C++多线程:condition_variable

C++多线程:condition_variable

时间:2024-11-01 19:59:04浏览次数:1  
标签:std 线程 notify variable 多线程 condition wait

条件变量

类似于pthread库中的pthread_cond_*()提供的功能,C++ 11标准提供了两种表示条件变量的类,分别是condition_variablecondition_variable_any,定义在头文件<condition_variable>

std::condition_variable

std::condition_variable对象调用wait()时,会阻塞当前线程,直到该std::condition_variable对象被另一线程notify_*()唤醒

构造函数

  • 默认构造
    condition_variable()
  • 拷贝构造
    condition_variable(const condition_variable&)=delete
    被禁用,不可拷贝

如下使用条件变量阻塞当前线程

std::mutex mtx;
std::condition_variable cv;

void print(int id) {
    std::unique_lock<std::mutex> lck(mtx);
    cv.wait(lck);
    // ...
}

成员函数

  1. std::condition_variable::wait()重载
  • unconditional
    void wait(unique_lock<mutex>&);
    
    在调用wait()前,此时线程应该是加锁状态,因为wait()在阻塞线程时,会自动调用lck.unlock()释放锁,使得其他被阻塞在锁竞争上的线程得以执行
    当前线程被另一线程notify_*()唤醒时,则会自动调用lck.lock()加锁,使得lck状态和wait()被调用时相同
  • predicate
    template<class Predition>
    void wait(unique_lock<mutex>&, Predition pred);
    
    仅在predfalse时,wait()才会阻塞当前线程
    当前线程被另一线程notify_*()唤醒时,仅在predtrue时才会解除阻塞
    类似于
    while(!pred){
      wait(lck);
    }
    
  1. std::condition_variable::wait_for()重载
  • unconditional
    template<class Rep, class Period>
    cv_status wait_for(unique_lock<std::mutex>&, const chrono::duration<Rep,Period>&)
    
    在当前线程被notify_*()唤醒前,或在指定时间段内,当前线程会处于阻塞状态
  • predicate
    template<class Rep, class Period, class Predicate>
    cv_status wait_for(unique_lock<std::mutex>&, const chrono::duration<Rep,Period>& rel_time, Predicate pred)
    
    仅在predfalse时,wait()才会阻塞当前线程
    当前线程被另一线程notify_*()唤醒时,仅在predtrue时才会解除阻塞
    类似于
    return wait_until(lck, chrono::steady_clock::now()+rel_time, std::move(pred));
    
  1. std::condition_variable::wait_until()重载
  • unconditional
    template<class Clock,class Duration>
    cv_status wait_until(unique_lock<mutex>&,const chrono::time_point<Clock,Duration>&)
    
    在当前线程被notify_*()唤醒前,或在指定时间点前,当前线程会处于阻塞状态
  • predicate
    template<class Clock, class Duration, class Predicate>
    cv_status wait_until(unique_lock<mutex>&, const chrono::time_point<Clock,Duration>& abs_time, Predicate pred)
    
    仅在predfalse时,wait()才会阻塞当前线程
    当前线程被另一线程notify_*()唤醒时,仅在predtrue时才会解除阻塞
    类似于
    while(!pred){
      if(wait_until(lck,abs_time)==cv_status::timeout){
          return pred;
      }
    }
    return true;
    
  1. std::condition_variable::notify_one()
    唤醒某个等待wait线程,若有多个等待线程,则唤醒的线程是不确定的

  2. std::condition_variable::notify_all()
    唤醒所有等待wait线程

std::condition_variable_any

std::condition_variable不同的是,std::condition_variable_anywait()可以接收任何lockable参数,如递归互斥锁、定时互斥锁等
std::condition_variablewait()仅可以接收std::unique_lock<std::mutex>类型

std::cv_status枚举类型

  • cv_status::no_timeout
    wait_for()wait_until()未超时,即在规定时间段内线程收到notify_*()通知
  • cv_status::timeout
    wait_for()wait_until()超时

辅助函数

std::notify_all_at_thread_exit()

函数原型

void std::notify_all_at_thread_exit(condition_variable& cond,unique_lock<std::mutex>);

当调用该函数的线程退出时,所有在cond条件变量上等待的线程都会收到通知

示例如下:

#include <iostream>
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable_any

std::mutex mtx;
std::condition_variable_any cv;
bool ready= false;

void print_id(int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while(!ready){
    cv.wait(lck);
  }
  std::cout << "thread id:" << id << std::endl;
}

void go() {
  std::unique_lock<std::mutex> lck(mtx);
  std::notify_all_at_thread_exit(cv, std::move(lck));
  ready= true;
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i){
        threads[i] = std::thread(print_id, i);
    }
    std::cout<< "10 threads ready to race..."<<std::endl;

    std::thread(go).detach();

    for (auto& th : threads) {
        th.join();
    }
    return 0;
}

通知丢失

虚假唤醒

标签:std,线程,notify,variable,多线程,condition,wait
From: https://www.cnblogs.com/sgqmax/p/18521170

相关文章

  • C++多线程:promise
    头文件包含:Providers类std::promisestd::packaged_taskFutures类std::futurestd::shared_futureProviders函数std::async()其他类型std::future_errorstd::future_errcstd::future_statusstd::launchstd::promise用来保存某一类型T的值,该值可以被future对......
  • C++多线程:package_task
    std::packaged_taskstd::packaged_task包装一个可调用对象,并允许获取该可调用对象计算的结果,可调用对象内部包含两个基本元素:1.被包装的任务任务是一个可调用对象,如函数指针或函数对象,该对象的执行结果会传递给共享状态2.共享状态用于保存任务的返回结果,并可通过future对象异......
  • 高并发IPC通信实现:HarmonyOS中的异步调用与多线程处理
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在当今的移动应用开发领域,高并发通信场......
  • 【JavaEE】【多线程】进阶知识
    目录一、常见的锁策略1.1悲观锁vs乐观锁1.2重量级锁vs轻量级锁1.3挂起等待锁vs自旋锁1.4普通互斥锁vs读写锁1.5可重入锁vs不可重入锁1.6不公平锁vs公平锁二、synchronized特性2.1synchronized的锁策略2.2synchronized加锁过程2.3其它优化措施三、......
  • Java多线程--Thread类的那些事3.--线程的6中状态和sleep()和 join()
      一.sleep()方法  首先在Thead类中有一个静态的sleep()方法,可以让线程进入到休眠状态即TEMD-WAITING状  在调用sleep()方法时需要注意的是在哪个线程里面调用sleep()方法,哪个线程就会进入阻塞状态.,在这个线程中的其他线程不会发生阻塞,只有当休眠时间到来这个......
  • Java 多线程中的通信机制
    本篇文章讲述了“Java多线程的通信机制”,阅读时长大约为:10分钟一、引言“Java多线程中的等待与通知机制”是一种线程间通信方式,用来协调线程的执行顺序和资源共享。通过这样子的机制,线程可以避免忙等待,提高资源利用率和程序执行效率。二、Java多线程中的通信机制概......
  • 多线程在打包工具中的运用
    我们是袋鼠云数栈UED团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:UED团队现代操作系统都是「多任务」的,也就是操作系统可以「并发」处理多个任务,比如可以在浏览页面的时候同时播放音乐。但是,一般来说我......
  • 多线程编程 Linux环境
    进程和线程相同点:都是参与时间片轮转的任务,都有5个状态不同点:线程不能独立存在,只能隶属于创建它的进程进程实际上是线程的容器,任何进程至少包含一个称为主线程的线程,执行main函数所在的执行序列,这个线程是系统为进程自动创建而其余线程则进程通过调用相关函数来创建进......
  • C++多线程应用
    一个进程就是一个程序,一个程序里不止一个功能,每个功能的实现就可以交给一个线程去完成。一个进程就像是一个工程,这个工程里,有设计,有监理,有施工,就相当于三个线程,各干各的又相互配合。https://cplusplus.com/reference/thread/thread/thread/是C++的官方参考,个人觉得比较权威,比经......
  • Linux系统基础-多线程超详细讲解(3)_线程互斥同步和条件变量
    个人主页:C++忠实粉丝欢迎点赞......