常用的c++新特性-->day09

原子变量

C++11提供了一个原子类型std::atomic,通过这个原子类型管理的内部变量就可以称之为原子变量,我们可以给原子类型指定bool、char、int、long、指针等类型作为模板参数(不支持浮点类型和复合类型)。
原子变量会把线程对数据的读、修改和存储变成一个原子操作,线程从内存读数据传给CPU,CPU再同步到物理内存 -> 三步不可拆分
互斥锁可以锁任意的数据类型,而原子变量只是针对于整形数据

案例

#include <iostream>
#include <thread>
#include <atomic>
#include <mutex>
using namespace std;#if 1
struct Base
{Base(int n, string s) :age(n), name(s) {}int age;string name;
};class Counter
{
public:void increment(){for (int i = 0; i < 100; ++i){//mtx.lock();number++;cout << "+++ increment thread id: " << this_thread::get_id() << ", number: " << number << endl;//mtx.unlock();this_thread::sleep_for(chrono::milliseconds(100));}}void increment1(){for (int i = 0; i < 100; ++i){//mtx.lock();number++;cout << "*** decrement thread id: " << this_thread::get_id()<< ", number: " << number << endl;//mtx.unlock();this_thread::sleep_for(chrono::milliseconds(50));}}
private://int number = 0;atomic_int number = 0;//atomic<Base*> base;//不能包装这个指针指向的数据块的线程安全,只能保证指针移动的线程安全  >>>> 因此必须要加锁//mutex mtx;
};int main()
{Counter c;thread t1(&Counter::increment, &c);thread t2(&Counter::increment1, &c);t1.join();t2.join();
#if 0atomic<char> c('a');atomic_char cc('b');atomic<int> b;atomic_init(&b, 9);cc = 'd';b.store(88);char ccc = c.exchange('e');Base base(123, "luffy");atomic<Base*> atc_base(&base);cout << "c value: " << c << endl;cout << "ccc value: " << ccc << endl;cout << "b value: " << b.load() << endl;Base* tmp = atc_base.load();cout << "name: " << tmp->name << ", age: " << tmp->age << endl;b = 12;
#endifreturn 0;
}
#endif

线程异步

线程异步在执行的时候多个线程不需要各自等待,各自执行各自的就行了
在一个线程里面获取到另外一个线程执行的结果

线程同步和线程异步

线程同步:A线程需要得到B线程的结果,在B线程工作的时候,A线程此时是阻塞等待的
线程异步:A线程需要得到B线程的结果,在B线程工作的时候,A线程此时是不会等待的
多线程程序中的任务大都是异步的,主线程和子线程分别执行不同的任务

std::future

std::future在主线中得到某个子线程任务函数返回的结果

std::promise

std::promise是一个协助线程赋值的类,它能够将数据和future对象绑定起来,为获取线程函数中的某个值提供便利。

promise的使用

通过promise传递数据的过程一共分为5步:

  • 在主线程中创建std::promise对象
  • 将这个std::promise对象通过引用的方式传递给子线程的任务函数
  • 在子线程任务函数中给std::promise对象赋值
  • 在主线程中通过std::promise对象取出绑定的future实例对象
  • 通过得到的future对象取出子线程任务函数中返回的值。

std::ref()

在外部主线程中创建的promise对象必须要通过引用的方式传递到子线程的任务函数中
在实例化子线程对象的时候,如果任务函数的参数是引用类型,那么实参一定要放到std::ref()函数中,表示要传递这个实参的引用到任务函数中

案例

有几个线程就要用几个future和几个promise

#include <iostream>
#include<thread>
#include<future>
using namespace std;
//在子线程执行任务的时候传出数据给到主线程//2、将promise对象通过引用方式传入子线程的任务函数
void func(promise<string>& p)
{this_thread::sleep_for(chrono::seconds(3));//3、给promise对象赋值p.set_value("我是你亲妈......");//调用后,主线程的get函数解除阻塞this_thread::sleep_for(chrono::seconds(3));//其他事情
}int main()
{//1、在主线程中创建promise对象promise<string> pro;promise<string> pro1;thread t1(func,ref(pro));//整个匿名函数可以看作为函数的地址 相当于有名函数的函数名thread t2([](promise<string>& p){this_thread::sleep_for(chrono::seconds(3));//3、给promise对象赋值p.set_value("我才是你亲妈......");//调用后,主线程的get函数解除阻塞this_thread::sleep_for(chrono::seconds(3));//其他事情},ref(pro1));//4、在主线程通过promise对象取出绑定的future实例对象future<string> f = pro.get_future();future<string> f1 = pro1.get_future();//5、通过得到的future对象取出子线程任务函数中返回的值string str = f.get();//get阻塞函数string str1 = f1.get();cout << "子线程的数据:" << str << endl;cout << "子线程的数据:" << str1 << endl;t1.join();t2.join();return 0;
}

在这里插入图片描述

std::packaged_task

这个类可以将内部包装的函数和future类绑定到一起,以便进行后续的异步调用,它和std::promise有点类似,std::promise内部保存一个共享状态的值,而std::packaged_task保存的是一个函数。

案例

#include <iostream>
#include <thread>
#include <future>
#include <string>
using namespace std;string myFunc()
{this_thread::sleep_for(chrono::seconds(3));return "我是路飞,要成为海贼王。。。";
}using funcPtr = string(*)(string, int);class Base
{
public://重载string operator()(string msg){string str = "operator() function msg: " + msg;return str;}operator funcPtr(){return showMsg;}int getNumber(int num){int number = num + 100;return number;}static string showMsg(string msg, int num){string str = "showMsg() function msg: " + msg + ", " + to_string(num);return str;}
};int main()
{
#if 1// 普通函数packaged_task<string(void)> task1(myFunc);// 匿名函数packaged_task<int(int)> task2([](int arg) {return 100;});// 仿函数Base ba;packaged_task<string(string)> task3(ba);// 将类对象进行转换得到的函数指针Base bb;packaged_task<string(string, int)> task4(bb);// 静态函数packaged_task<string(string, int)> task5(&Base::showMsg);// 非静态函数Base bc;auto obj = bind(&Base::getNumber, &bc, placeholders::_1);packaged_task<int(int)> task6(obj);thread t1(ref(task6), 200);future<int> f = task6.get_future();int num = f.get();cout << "子线程返回值: " << num << endl;t1.join();
#endifreturn 0;
}

std::async

td::async函数比前面提到的std::promise和packaged_task更高级一些,因为通过这函数可以直接启动一个子线程并在这个子线程中执行对应的任务函数,异步任务执行完成返回的结果也是存储到一个future对象中,当需要获取异步任务的结果时,只需要调用future 类的get()方法即可,如果不关注异步任务的结果,只是简单地等待任务完成的话,可以调用future 类的wait()或者wait_for()方法。

案例

#include <iostream>
#include <thread>
#include <future>
#include <string>
using namespace std;string myFunc()
{this_thread::sleep_for(chrono::seconds(3));return "我是路飞,要成为海贼王。。。";
}using funcPtr = string(*)(string, int);
class Base
{
public:string operator()(string msg){string str = "operator() function msg: " + msg;return str;}operator funcPtr(){return showMsg;}int getNumber(int num){int number = num + 100;return number;}static string showMsg(string msg, int num){string str = "showMsg() function msg: " + msg + ", " + to_string(num);return str;}
};int main()
{
#if 1cout << "主线程线程ID: " << this_thread::get_id() << endl;future<string> f = async(launch::async, [](int number) {cout << "子线程线程ID: " << this_thread::get_id() << endl;return string("我是海贼王... ") + to_string(number);}, 100);this_thread::sleep_for(chrono::seconds(10));cout << "子线程的返回值: " << f.get() << endl;
#endif
#if 0future<string> f = async([](int number) {this_thread::sleep_for(chrono::seconds(3));cout << "子线程线程ID: " << this_thread::get_id() << endl;return string("我是海贼王... ") + to_string(number);}, 100);future_status status;do {status = f.wait_for(chrono::seconds(1));if (status == future_status::deferred){cout << "子线程还没有执行..." << endl;f.wait();}else if (status == future_status::ready){cout << "数据就绪了, 子线程返回的数据是: " << f.get() << endl;}else if (status == future_status::timeout){cout << "子线程还在执行, 超时时长用完了, 继续等待..." << endl;}} while (status != future_status::ready);
#endifreturn 0;
}

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/13936.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

新的服务器Centos7.6 安装基础的环境配置(新服务器可直接粘贴使用配置)

常见的基础服务器配置之Centos命令 正常来说都是安装一个docker基本上很多问题都可以解决了&#xff0c;我基本上都是通过docker去管理一些容器如&#xff1a;mysql、redis、mongoDB等之类的镜像&#xff0c;还有一些中间件如kafka。下面就安装一个 docker 和 nginx 的相关配置…

RAG与知识库搭建,手把手教你构建RAG系统

0. 简介 自从发现可以利用自有数据来增强大语言模型&#xff08;LLM&#xff09;的能力以来&#xff0c;如何将 LLM 的通用知识与个人数据有效结合一直是热门话题。关于使用微调&#xff08;fine-tuning&#xff09;还是检索增强生成&#xff08;RAG&#xff09;来实现这一目标…

【数据结构】10.线索二叉树

一、线索二叉树的产生 采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列&#xff0c;序列上的每一个结点&#xff08;除了第一个和最后一个&#xff09;都有一个前驱和一个后继&#xff0c;但是&#xff0c;这个线性序列只是逻辑的概念&#xff0c;不是物理结…

java实现中小企业的erp系统

项目介绍 技术架构: springboot3jdk17mybatis-plusmysql8kotlinvueuniappelementui等

企业软文营销如何以差异化卖点助力品牌市场曝光?媒介盒子分享

对于市场竞争日益激烈的现下&#xff0c;企业想要获取优势&#xff0c;从市场中脱颖而出并能吸引到更多的消费者&#xff0c;学会创建或找寻到自身的差异点是至关重要的。常言讲“物以稀为贵”&#xff0c;对于消费者而言&#xff0c;品类相同中的品牌需要去以“不同”来获取用…

探索Pillow库:Python图像处理的瑞士军刀

文章目录 **探索Pillow库&#xff1a;Python图像处理的瑞士军刀**1. 背景&#xff1a;为何选择Pillow&#xff1f;2. Pillow是什么&#xff1f;3. 如何安装Pillow&#xff1f;4. 五个简单的库函数使用方法4.1 打开图像4.2 显示图像4.3 转换图像格式4.4 调整图像大小4.5 旋转图像…

快速入门Selenium自动化测试

一、背景与意义 Selenium是常用的Web自动化测试工具&#xff0c;前端开发工程师可以在完成每项开发任务之后&#xff0c;使用Selenuim做一下回归测试&#xff0c;以避免被提BUG太多导致后面做项目总结时太难看。测试工程师学习Selenium时需要掌握很多API接口&#xff0c;例如页…

Java基础-内部类与异常处理

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、Java 内部类 什么是内部类&#xff1f; 使用内部类的优点 访问局部变量的限制 内部类和继承 内部…

HCIP—MSTP(多生成树协议)

目录 一、MSTP技术的背景 二 、MSTP&#xff08;多生成树协议&#xff09;的概述 三、MSTP的基本概念 四、MSTP的实验配置 MSTP的引入&#xff1a;单点故障——冗余——二层环路——STP——RSTP——MSTP 一、MSTP技术的背景 单生成树的弊端—部分VLAN路径不同 单生成树的弊…

光控资本:中字头,多股涨停!融资客大举加仓

11月13日&#xff0c;受昨夜外盘心境影响&#xff0c;A股三大指数集体低开&#xff0c;沪指盘中翻红&#xff0c;A50期货指数快速拉升。 当时A股心境并未降温&#xff0c;代表商场急进心境的融资余额数据继续攀升&#xff0c;现在仅次于2015年牛市高点。‍‍‍ 从近期的盘面来…

项目功能--项目介绍(健康管理系统)

一、项目介绍 健康管理系统是一款应用于健康管理机构的业务系统&#xff0c;实现健康管理机构工作内容可视化、会员管理专业化、健康评估数字化、健康干预流程化、知识库集成化&#xff0c;从而提高健康管理师的工作效率&#xff0c;加强与会员间的互动&#xff0c;增强管理者对…

【深度学习目标检测|YOLO算法4-4】YOLO家族进化史:从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析——工业领域

【深度学习目标检测|YOLO算法4-4】YOLO家族进化史&#xff1a;从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析——工业领域 【深度学习目标检测|YOLO算法4-4】YOLO家族进化史&#xff1a;从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析——工业领域 文章目录…

Warped Universe游戏即将在Sui上推出,为玩家提供多样化的游戏体验

Warped Games选择Sui作为其即将推出的创新多类型游戏Warped Universe的首选Web3技术。Warped Universe让玩家可以体验第三视角实时动作、回合制策略和基地建设等玩法。该游戏使用Unreal Engine 5开发&#xff0c;将借助Sui的技术使玩家能够拥有、交易和变现其游戏内资产。 War…

【数据运营】数据治理与运营新纪元:全面解析数据治理平台与运营体系建设方案

踏入数据治理与运营的新纪元,我们迎来了一场深刻变革。本篇文章将带您全面解析数据治理平台与数据运营体系的建设方案,为您揭示数据治理的总体解决策略,探索数据治理平台构建的奥秘,以及数据治理运营实施的具体路径。 数据治理总体解决方案是数据治理与运营体系建设…

PyCharm2024.2.4安装

一、官网下载 1.从下面的链接点进去 PyCharm: The Python IDE for data science and web development by JetBrains 2.进入官网后,下载pycharm安装包 3.点击下载能适配你系统的安装包 4.安装包下载完成 二、安装 1.下载完成后,打开点击右键,打开 2.下一步

【无人机设计与控制】线性和非线性模型预测MPC、NMPC四旋翼无人机轨迹跟踪

摘要 本文研究了四旋翼无人机的线性和非线性模型预测控制&#xff08;MPC与NMPC&#xff09;算法在轨迹跟踪中的应用。通过Matlab/Simulink仿真实现了四旋翼无人机在复杂环境中的高效轨迹跟踪。研究结果表明&#xff0c;NMPC比传统MPC在处理非线性动态和外部扰动时具有更好的鲁…

如何用Java爬虫“偷窥”淘宝商品类目API的返回值

在这个数据为王的时代&#xff0c;获取信息就像是在玩一场大型的寻宝游戏。而淘宝&#xff0c;作为电商界的巨人&#xff0c;其商品类目API就像是藏宝图上的秘密标记。今天&#xff0c;我们就来聊聊如何用Java爬虫技术&#xff0c;悄悄地“偷窥”这些宝藏。 准备工作&#xff1…

2024最新网络安全自学路线,内容涵盖3-5年技能提升

01 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

模拟实现优先级队列

目录 定义 特点 构造函数 常用方法 关于扩容的问题 关于建堆的问题 向上调整和向下调整的比较 &#xff08;向上调整&#xff09;代码 &#xff08;向下调整&#xff09;代码 关于入队列和出队列问题 模拟实现优先级队列代码 关于堆排序的问题 堆排序代码 关于对…

Django 搭建数据管理web——商品管理

教材&#xff1a; python web 企业级项目开发教程 黑马程序员 5.4 实例1&#xff1a;商品管理 实验步骤&#xff1a; 1.创建项目&#xff08;任意名字&#xff09;和应用&#xff08;goods&#xff09; 2.在项目文件夹&#xff08;manage.py文件所在路径&#xff09;新建te…