返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++11 condition_variable条件变量怎么使用
  • 845
分享到

C++11 condition_variable条件变量怎么使用

2023-07-02 17:07:07 845人浏览 安东尼
摘要

今天小编给大家分享一下c++11 condition_variable条件变量怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们

今天小编给大家分享一下c++11 condition_variable条件变量怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

1 什么是条件变量

condition_variable是一个类,常和mutex搭配使用。

condition_variable类是一个同步原语,可用于阻塞一个线程或同时阻止多个线程,直到另一个线程修改共享变量并通知condition_variable。

防止多线程场景下,共享变量混乱。

理解条件变量要先理解三个概念:

  • (锁住共享变量,线程独占)

  • wait 等待 (等待通知条件变量,变化的共享变量是否满足条件)

  • notify 通知 (通知等待的条件变量,共享变量发送变化)

2 condition_variable类定义

C++11 condition_variable条件变量怎么使用

2.1 wait函数

void wait( std::unique_lockstd::mutex& lock );//Predicate是lambda表达式。template< class Predicate >void wait( std::unique_lockstd::mutex& lock, Predicate pred );//以上二者都被notify_one())或notify_broadcast()唤醒,但是//第二种方式是唤醒后也要满足Predicate的条件。//如果不满足条件,继续解锁互斥量,然后让线程处于阻塞或等待状态。//第二种等价于while (!pred()){wait(lock);}

3 condition_variable用法

condition_variable必定至少有两方,一方是资源修改线程,一方是资源等待线程。就跟打篮球一样,同时篮球只会在一个人手中,投篮后就释放了篮球所有权,其他方就会抢夺篮球所有权。

3.1 资源修改线程步骤

  • 获取一个mutex使用 std::unique_lock< std::mutex >

  • 保持锁定状态,修改共享变量

  • condition_variable对象执行notify_one或者notify_all(notify_one/notify_all执行前可以释放锁)

3.2 资源等待线程步骤

  • 获取一个mutex使用 std::unique_lock< std::mutex > unlock用于保护要修改的共享变量

  • 检查条件变量,

(1)条件变量满足,线程继续执行

(2)条件变量不满足,wait会释放unlock锁,并挂起线程。

  • 当notify通知条件变量、超时过期或发生虚假唤醒时,线程被唤醒,互斥锁unlock被原子地重新获取。然后,线程应该检查条件,如果唤醒是假的,则继续等待

4 代码示例

4.1 无需notify场景

当wait第一次执行是,条件已经满足,则程序不会阻塞(即无需notify),会直接向下执行。(仅为说明3.2 中第2点(1)的情况)

#include <iOStream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件满足无需notify,不阻塞向下执行"  << endl;    cv.wait(lk, []{return ready;});     // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "5、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::cout << "6、worker_thread子线程交出执行权限,主线程执行"  << endl;    std::this_thread::sleep_for(std::chrono::milliseconds(2000));        cv.notify_one();    std::cout << "9、worker_thread调用 notify_one"  << endl;}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::lock_guard<std::mutex> lk(m);        ready = true;    }    std::cout << "2、锁已经释放了,主线程休眠,子线程执行"  << std::endl;    std::this_thread::sleep_for(std::chrono::milliseconds(1000));    //cv.notify_one();    {        std::cout << "7、主线程data:" << data << endl;        std::unique_lock<std::mutex> lk(m);        std::cout << "8、主线程条件满足无需notify" << endl;        cv.wait(lk, []{return processed;});    }        worker.join();     std::cout << "10、主线程结束" << endl;}

执行结果:

C++11 condition_variable条件变量怎么使用

4.2 正常应用场景1

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件不满足,释放lk锁,子线程阻塞"  << endl;    cv.wait(lk, []{return ready;});    std::cout << "8、worker_thread子线程获取到锁,子线程继续执行"  << endl;    // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "9、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::this_thread::sleep_for(std::chrono::milliseconds(5000));    std::cout << "10、worker_thread调用 notify_one通知主线程执行"  << endl;    cv.notify_one();}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        std::cout << "2、主线程休眠,子线程进入执行"  << std::endl;        std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::cout << "5、主线程结束休眠,主线程获取lk锁,进入执行"  << std::endl;        std::lock_guard<std::mutex> lk(m);        ready = true;            }    std::cout << "6、主线程释放lk,调用notify通知子线程"  << std::endl;    cv.notify_one();    {        std::cout << "7、由于主线程的执行时钟周期未结束,继续执行主线程获取lk, wait检查条件不满足,释放锁" << endl;        std::unique_lock<std::mutex> lk(m);        cv.wait(lk, []{return processed;});    }       worker.join();     std::cout << "11、主线程结束" << endl;}

执行结果:

这里notify执行后不一定立即执行子线程,如果cpu执行时钟周期未结束,则主线程会继续执行. 所以7,8,9,10顺序可能变化参见4.3

同时4.1也会因为cpu时钟周期,执行顺序有所变动

C++11 condition_variable条件变量怎么使用

4.3 正常应用场景2

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件不满足,释放lk锁,子线程阻塞"  << endl;    cv.wait(lk, []{return ready;});    std::cout << "8、worker_thread子线程获取到锁,子线程继续执行"  << endl;    // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "9、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::cout << "10、worker_thread调用 notify_one通知主线程执行"  << endl;    cv.notify_one();}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        std::cout << "2、主线程休眠,子线程进入执行"  << std::endl;        std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::cout << "5、主线程结束休眠,主线程获取lk锁,进入执行"  << std::endl;        std::lock_guard<std::mutex> lk(m);        ready = true;            }    std::cout << "6、主线程释放lk,调用notify通知子线程"  << std::endl;    cv.notify_one();    {        for(int i = 0; i< 10000000; i++)        {            int j = i;        }        std::cout << "7、由于主线程的执行时钟周期未结束,继续执行主线程获取lk, wait检查条件不满足,释放锁" << endl;        std::unique_lock<std::mutex> lk(m);        cv.wait(lk, []{return processed;});    }        worker.join();    std::cout << "11、主线程结束" << endl;}

执行结果:

C++11 condition_variable条件变量怎么使用

以上就是“C++11 condition_variable条件变量怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网其他教程频道。

--结束END--

本文标题: C++11 condition_variable条件变量怎么使用

本文链接: https://lsjlt.com/news/343224.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++11 condition_variable条件变量怎么使用
    今天小编给大家分享一下C++11 condition_variable条件变量怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们...
    99+
    2023-07-02
  • C++11 condition_variable条件变量的用法说明
    目录1 什么是条件变量2 condition_variable类定义2.1 wait函数3 condition_variable用法3.1 资源修改线程步骤3.2 资源等待线程步骤4...
    99+
    2024-04-02
  • C++11线程、互斥量及条件变量怎么创建
    这篇“C++11线程、互斥量及条件变量怎么创建”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++11线程、互斥量及条件变量...
    99+
    2023-07-05
  • 怎么理解C++11 中的线程及锁和条件变量
    今天就跟大家聊聊有关怎么理解C++11 中的线程及锁和条件变量,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。线程类std::thread代表一个可执行线程,使用时必须包含头文件<...
    99+
    2023-06-17
  • 详解C++11中的线程锁和条件变量
    目录线程锁条件变量小结线程 std::thread类, 位于<thread>头文件,实现了线程操作。std::thread可以和普通函数和 lambda 表达式搭配使用。...
    99+
    2024-04-02
  • C++11中线程、锁和条件变量的介绍
    这篇文章主要介绍“C++11中线程、锁和条件变量的介绍”,在日常操作中,相信很多人在C++11中线程、锁和条件变量的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++11中线程、锁和条件变量的介绍”的疑...
    99+
    2023-06-17
  • C++11中线程锁和条件变量的示例分析
    这篇文章主要介绍了C++11中线程锁和条件变量的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。线程std::thread类, 位于<thread>头文件,...
    99+
    2023-06-15
  • c++多线程要使用条件变量的原因
    小编给大家分享一下c++多线程要使用条件变量的原因,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!先看示例1:#include <iostream&...
    99+
    2023-06-15
  • c++多线程为何要使用条件变量详解
    先看示例1: #include <iostream> #include <windows.h> #include <mutex> #inclu...
    99+
    2024-04-02
  • C++11可变参数模板怎么使用
    本篇内容主要讲解“C++11可变参数模板怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++11可变参数模板怎么使用”吧!可变参数函数C语言中,可变参数函数可以说是一个比较神奇的存在。例...
    99+
    2023-06-19
  • 使用条件变量的坑有哪些
    本篇内容介绍了“使用条件变量的坑有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 什么是...
    99+
    2024-04-02
  • 怎么使用C++11-20常量表达式
    这篇文章主要讲解了“怎么使用C++11-20常量表达式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用C++11-20常量表达式”吧!C++98时代C++98编译器对int常量情有独钟...
    99+
    2023-06-25
  • C++11的swap怎么使用
    这篇文章主要介绍“C++11的swap怎么使用”,在日常操作中,相信很多人在C++11的swap怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++11的swap怎么使用”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-19
  • C++11的sizeof怎么使用
    本篇内容介绍了“C++11的sizeof怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!示例说明假设有一个程序,需要接受文字信息并生成...
    99+
    2023-06-19
  • C++中怎么定义和使用变量
    这篇文章将为大家详细讲解有关C++中怎么定义和使用变量,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C++定义变量有两种主要的做法 符号常量 (#define) 常值变量 (const)符号...
    99+
    2023-06-17
  • c#文件路径引用变量怎么写
    在 c# 中,您可以通过字符串插值或 string.format 方法将变量引用到文件路径中。字符串插值使用 ${} 语法,而 string.format 方法需要提供格式字符串和要插入...
    99+
    2024-05-14
    c#
  • GoLang并发编程中条件变量sync.Cond的使用
    目录一、条件变量与互斥锁二、条件变量与互斥锁的配合使用三、条件变量的使用创建锁和条件使用四、条件变量的Wait方法做了什么一、条件变量与互斥锁 条件变量是基于互斥锁的,它必须基于互斥...
    99+
    2023-01-10
    Go sync.Cond介绍 Go sync.Cond使用
  • c++怎么把变量变为常量
    在 c++ 中,使用 const 关键字可将变量变为常量,常量保持不变且不可重新赋值。常量变量必须在定义时初始化,可参与数学运算,用于确保值不变、控制函数参数和提高代码可读性。 如何将...
    99+
    2024-05-14
    c++
  • C#枚举变量怎么用
    本篇内容主要讲解“C#枚举变量怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#枚举变量怎么用”吧!实例下面的实例演示了枚举变量的用法:using System;public&n...
    99+
    2023-06-17
  • C#静态函数及变量怎么使用
    本篇内容介绍了“C#静态函数及变量怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!学习C#静态方法之前我们首先来看看C#静态函数及变量...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作