首页 > 其他分享 >条件变量condition_variable

条件变量condition_variable

时间:2024-03-25 15:24:30浏览次数:24  
标签:std 变量 线程 variable data condition wait

C++标准库对条件变量有两套实现:std::condition_variablestd::condition_variable_any 。 这两个实现都包含在 <condition_variable> 头文件的声明中。 两者都需要与一个互斥量一起才能工作(互斥量是为了同步); 前者仅限于与 std::mutex 一起工作, 而后者可以和任何满足最低标准的互斥量一起工作, 从而加上了_any的后缀。  

std::condition_variable 构造函数

condition_variable(); //default
condition_variable (const condition_variable&) = delete; // copy delete

看一个例子:

std::mutex mut;
std::queue<data_chunk> data_queue; // 1
std::condition_variable data_cond;
void data_preparation_thread()
{
    while(more_data_to_prepare())
    {
         data_chunk const data=prepare_data();
         std::lock_guard<std::mutex> lk(mut);
         data_queue.push(data); // 2
         data_cond.notify_one(); // 3
     }
} 
void data_processing_thread()
{
    while(true)
    {
         std::unique_lock<std::mutex> lk(mut); // 4
         data_cond.wait(lk,[]{return !data_queue.empty();}); // 5
         data_chunk data=data_queue.front();
         data_queue.pop();
         lk.unlock(); // 6
         process(data);
         if(is_last_chunk(data))
             break;
     }
}

首先, 你拥有一个用来在两个线程之间传递数据的队列①。 当数据准备好时, 使用 std::lock_guard 对队列上锁, 将准备好的数据压入队列中②, 之后线程会对队列中的数据上锁。 然后调用 std::condition_variablenotify_one()成员函数, 对等待的线程(如果有等待线程)进行通知③。 

在另外一侧, 你有一个正在处理数据的线程, 这个线程首先对互斥量上锁, 但在这std::unique_lock 要比 std::lock_guard ④更加合适。 线程之后会调用 std::condition_variable 的成员函数wait(), 传递一个锁和一个lambda函数表达式(作为等待的条件⑤)。 在这个例子中, 简单的lambda函数[]{return !data_queue.empty();}会去检查data_queue是否不为空, 当data_queue不为空——那就意味着队列中已经准备好数据了。 

std::condition_variable::wait()

void wait (unique_lock<mutex>& lck); // unconditional 
template <class Predicate>
    void wait (unique_lock<mutex>& lck, Predicate pred); // predicate

std::condition_variable 提供了两种 wait() 函数。当前线程调用 wait() 后将被阻塞(此时当前线程应该获得了锁(mutex),不妨设获得锁 lck),直到另外某个线程调用 notify_* 唤醒了当前线程。

在线程被阻塞时,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和 wait 函数被调用时相同。 这就是为什么用 std::unique_lock 而不使用 std::lock_guard —等待中的线程必须在等待期间解锁互斥量, 并在这这之后对互斥量再次上锁, 而 std::lock_guard 没有这么灵活。  

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

std::condition_variable::wait_for() 

template <class Rep, class Period>
  cv_status wait_for (unique_lock<mutex>& lck,
                      const chrono::duration<Rep,Period>& rel_time); // unconditional 

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

与 std::condition_variable::wait() 类似,不过 wait_for 可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。而一旦超时或者收到了其他线程的通知,wait_for 返回,剩下的处理步骤和 wait() 类似。wait_for 的重载版本(predicte)的最后一个参数 pred 表示 wait_for 的预测条件,只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。

std::condition_variable::wait_until

template <class Clock, class Duration>
  cv_status wait_until (unique_lock<mutex>& lck,
                        const chrono::time_point<Clock,Duration>& abs_time); // unconditional 

template <class Clock, class Duration, class Predicate>
       bool wait_until (unique_lock<mutex>& lck,
                        const chrono::time_point<Clock,Duration>& abs_time,
                        Predicate pred); // predicate 

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

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

std::condition_variable::notify_one() 

唤醒某个等待(wait)线程。如果当前没有等待线程,则该函数什么也不做,如果同时存在多个等待线程,则唤醒某个线程是不确定的(unspecified)。

std::condition_variable::notify_all()

唤醒所有的等待(wait)线程。如果当前没有等待线程,则该函数什么也不做。

 

标签:std,变量,线程,variable,data,condition,wait
From: https://www.cnblogs.com/love-9/p/18094422

相关文章

  • MacOS配置环境变量
    1.打开终端,默认状态如下:2.zsh对应的配置文件在用户根目录.zshrc文件下,直接使用vi.zshrc命令打开文件,按i进入新增模式。配置环境变量export="$PATH:/文件路径",例如配置/usr/bin/java、/opt/homebrew/binexport="$PATH:/usr/bin/java"export="$PATH:/opt/homebrew/bin"......
  • python3.6 使用调用栈储存上下文变量
    python3.6使用调用栈储存上下文变量从python3.7开始,新增contextvars模块,用于储存上下文变量.使用场景#python3.7fromcontextvarsimportContextVarimportasynciouser=ContextVar('var')asyncdefb():u=user.get()print(f'getname{u}')......
  • IT15527: IN SPECIFIC TIMING CONDITIONS WITH MULTIPLE DB2READLOG API CALLERS(CDC,
    IT15527:INSPECIFICTIMINGCONDITIONSWITHMULTIPLEDB2READLOGAPICALLERS(CDC,ETC),"NOROOMFORRETRIEVEDLOG"occursindb2diag.loghttps://www.ibm.com/mysupport/s/defect/aCI0z000000TOfW/dt010963?language=en_USDescription 1.  Proble......
  • 基于R语言的GD库实现地理探测器并自动将连续变量转为类别变量
      本文介绍基于R语言中的GD包,依据栅格影像数据,实现自变量最优离散化方法选取与执行,并进行地理探测器(Geodetector)操作的方法。  首先,在R语言中进行地理探测器操作,可通过geodetector包、GD包等2个包实现。其中,geodetector包是地理探测器模型的原作者团队开发的,其需要保证输入的......
  • Spark重温笔记(三):Spark在企业中为什么能这么强?——持久化、Checkpoint机制、共享变量与
    Spark学习笔记前言:今天是温习Spark的第3天啦!主要梳理了Spark核心数据结构:RDD(弹性分布式数据集),包括RDD持久化,checkpoint机制,spark两种共享变量以及spark内核调度原理,希望对大家有帮助!Tips:"分享是快乐的源泉......
  • C++共享之道:用extern实现源文件变量与类成员函数的巧妙共享
    概述:在C++中,使用`extern`关键字可实现在源文件之间共享变量与类成员函数。通过声明变量或类在头文件中,再在一个源文件中定义,其他源文件通过`extern`引用,促使模块化、可维护的代码组织。在C++中,extern关键字可用于在源文件之间共享变量。它告诉编译器某个变量的声明在其他源文......
  • react中什么时候使用useRef,直接在外层定义普通的变量可以吗
    react中什么时候使用useRef,直接在外层定义普通的变量可以吗在React中,useRef主要是用来创建一个可变的引用对象,它可以用来保存任何可变值,而且这个引用在组件重新渲染时始终保持不变。以下是几个典型使用场景:访问DOM元素:当你需要直接访问HTML元素时,可以使用useRef创建一个引......
  • 【Linux】详谈命令行参数&&环境变量
    目录一、浅谈命令行参数二、环境变量2.1环境变量的内涵以及理解2.2PATH环境变量:2.3输入程序名就能运行我们的程序2.4系统中的环境变量2.5导出环境变量 三、main函数的第三个参数3.1获得环境变量的三种方法 四、本地变量一、浅谈命令行参数        我......
  • 1.变量与数据类型、输出与输入
    C语言语法知识点1.变量与数据类型、输出与输入C中每个变量都有特定的类型,类型决定了变量存储的大小。变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。有以下几种基本的变量类型:类型char字符型,1字节(1字节8位,即1字节=8bit)int整型,4字节......
  • EI级!高创新原创未发表!VMD-TCN-BiGRU-MATT变分模态分解卷积神经网络双向门控循环单元融
    EI级!高创新原创未发表!VMD-TCN-BiGRU-MATT变分模态分解卷积神经网络双向门控循环单元融合多头注意力机制多变量时间序列预测(Matlab)目录EI级!高创新原创未发表!VMD-TCN-BiGRU-MATT变分模态分解卷积神经网络双向门控循环单元融合多头注意力机制多变量时间序列预测(Matlab)预测......