C++ 概览并发

news2024/11/24 2:22:11

并发

资源管理

资源

  • 程序中符合先获取后释放(显式或隐式)规律的东西,比如内存、锁、套接字、线程句柄和文件句柄等。
  • RAII: (Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。
unique_ptr & shared_ptr
  • unique_ptr 是一个独立对象或者是数组的句柄,unique_ptr 通过移动操作使得简单高效
  • shared_ptr 很多方面和unique_ptr 相似, 唯一区别是shared_ptr 通过拷贝操作而非移动操作。多个shared_ptr 共享该对象的所有权,只有当最后一个 shared_ptr 被销毁时,对象才被销毁。
  • shared_ptr 提供的垃圾回收机制需要慎重使用。 shared_ptr 使得对象的生命周期变得不那么容易掌控了,除非在一定程度上一定要使用共享所有权,否则别轻易使用shared_ptr
  • shared_ptr 没有指定哪个拥有者有权读写对象
  • 当我们使用函数返回集合的时候,不必使用指针,因为如果定义了移动语义, 在返回的时候会默认使用移动操作

并发

任务 和thread

  • 线程(thread)是任务在程序中的系统级表示。
  • thread 在 中定义
thread 的使用方法
#include <iostream>
#include <thread>
#include <vector>
#include "config.h"

// thead 的使用
// 函数的参数这里必须是const, 否则会报thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
// 在多线程中使用io 操作,需要考虑线程安全,打印出来的字符服务保证输出内容的顺序
void f(const std::vector<double>& v) {
	std::cout<< "function f" << std::endl;
}
// 通过res 指针返回thread 的执行结果,不美观的方法
// 不推荐使用此方法,因为无法掌控res 什么时候写入了,一般用消息队列,或者使用condition 、promise等方式来实现返回结果
void f2(const std::vector<double>& v, double* res) {

}

struct F {
	std::vector<double> & v;
	F(std::vector<double>& vv):v{vv} {

	}
	/* 如果不使用调用运算符重载, 会编译报错: hread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
	*/
	void operator()() {   // 调用运算符重载
		std::cout << "struct F  operator" << std::endl;

	}

};

class Foo
{
public:
    void bar()
    {
        for (int i = 0; i < 5; ++i)
        {
            std::cout << "正在执行线程3\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};


int main(int argc, char **argv) {
	std::vector<double> some_vec {1,2,3,4,5,6};
	std::vector<double> vec2{10,11,12,13};

	std::thread t1{f, some_vec}; // 在t1 的线程里面执行函数f, 参数是some_vec
	std::thread t2{F{vec2}};	// 在t2 的县城里面执行函数 F 的调用运算符, 参数是vec2
	double res;
	std::thread t3(f2, some_vec, &res);
	Foo f;
	std::thread t4(&Foo::bar, &f); // t5 在对象 f 上运行 foo::bar()
	t1.join();
	t2.join();
	return 0;
}


  • thread 更多用法清参照cppreference
thread 共享数据
  • mutex // 访问数据排他处理
  • condition_variable 允许一个thread 等待另外一个thread
  • 代码示例
class Message {
private:
    int msgId;
public:
    Message(int id) : msgId(id){

    }
    int getId() { return msgId;}
};

std::queue<Message> mMsgQueue;
std::condition_variable mCond;
std::mutex mMutex;

void consumer() {
    while(true) {
    	//std::cout << "wait mutex " <<  std::endl;
        std::unique_lock<std::mutex> lck{mMutex};
        //std::cout << "wait condition " <<  std::endl;
        //while(mCond.wait(lck))/*do nothing*/;
        mCond.wait(lck);
        //std::cout << "after wait condition " <<  std::endl;
        auto m = mMsgQueue.front();
        mMsgQueue.pop();
        std::cout << "get msg Id: " << m.getId() << std::endl;
        // lck.unlock();

    }
}

void producer() {
    int index = 10;
    while(index > 0) {
        Message msg(index);

        std::unique_lock<std::mutex> lck{mMutex};
        mMsgQueue.push(msg);
        std::cout << "push msg Id: " << msg.getId() << std::endl;
        lck.unlock(); //(1)
        mCond.notify_all();
        //std::cout << "after notify all: " << msg.getId() << std::endl;
        //std::this_thread::sleep_for(std::chrono::milliseconds(20)); //(2)

        index--;

    }
}

int main(int argc, char **argv) {
	std::thread t2(consumer);
    std::thread t1(producer);

    t1.join();
    t2.join();
}
  • 对于生产者-消费者模式,理想状态下,生产者生产一个,消费者就消费一个,但是实际并非如此

    • (1) 如果不主动调用lck.unlock(), lck 需要等到while(){} 进入下一个循环才会释放,所以无论是否加(), cosumer 线程得不到执行的契机(可能和平台有关)
    • (2) 对于加了(1) 而没有(2) 的场合while 很快执行到下一个循环,又立即执行到lck, 也会导致在producer 执行过程中,consumer 得不到执行
      执行效果大致如下:
      在这里插入图片描述
  • 而如果加了(1) 和(2)后:

    在这里插入图片描述

  • 对于consume 如上图的处理方式,获取一次锁只pop 一次数据,会因为producer notify 和consumer 的wait 不是时间上不是匹配出现而导致数据没有被全部读取出来,可以修改为如下方式:

  • 在获取到一次锁后,把消息队列中的消息全部处理掉

void consumer() {
    while(true) {
    	//std::cout << "wait mutex " <<  std::endl;
        std::unique_lock<std::mutex> lck{mMutex};
        //std::cout << "wait condition " <<  std::endl;
        //while(mCond.wait(lck))/*do nothing*/;
        mCond.wait(lck);
        //std::cout << "after wait condition " <<  std::endl;
        while(!mMsgQueue.empty()) {
            auto m = mMsgQueue.front();
            mMsgQueue.pop();
            std::cout << "get msg Id: " << m.getId() << std::endl;
        }
  
        // lck.unlock();

    }
}

执行效果大致如下, 这样只是消费者不会立马消费掉生产者生产的数据,但是即使没有(1)(2)也不会导致消息得不到处理:
在这里插入图片描述

任务通信

  • c++ 中主要提供了以下三种,都定义在 头文件中。
    • future and promise 用来从一个独立线程上创建出的任务返回结果
    • packaged_task 是帮助启动义务以及链接返回结果的机制
    • async 以非常类似调用函数的方式启动一个任务
future and promis
  • 允许两个任务间传输直,而无须显示使用锁–“系统”高效地实现了这种传输。
    • 当一个任务需要向另一个任务传输这个值时,把它放入promise。
    • c++ 实现会出现在对应的future 中。
    • 使用future 的get()函数,如果值还未准备好,线程会阻塞直至值准备好。如果get( )无法计算出来,get()会抛一个异常(系统或者从get() 得到数据的任务)
    • promise 的作用主要为future的get() 提供放置 操作(set_value()) 和set_exception().
#include <iostream>
#include <thread>
#include <future>
#include <functional>
void work (std::promise<int>& px) {
    try {
        px.set_value(11);
    } catch (...) {
        px.set_exception(std::current_exception());
    }
}

void result (std::future<int>& res) {
    
    try {
        int result = res.get();
        std::cout<< " recieve the result: " << result << std::endl;
    } catch(...) {
        //std::cout<<"exception"<< std::current_exception() << std::endl;
    }
}
int main(int argc, char **argv) {
    std::promise<int> pro;
    std::future<int> fut = pro.get_future(); //binding the future and the promise

    
	std::thread t1(work, std::ref(pro));
    std::thread t2(result, std::ref(fut));

    t1.join();
    t2.join();
    return 0;
}

  • 可以看到使用步骤如下:

    • 声明promise
    • 定义future,并且绑定promise 和future, 二者的模板类型必须一致(很好理解,provise 设定的就是传给future 的)
    • 使用promise 的set_value()或者set_exception() 传递值
    • 使用future 的get() 函数接收值(注意get()是阻塞的)
  • 这里使用了std::ref std::ref的使用场景:

    • 算法传递可调用对象,而这些对象可能需要引用传递。
    • 在多线程之间共享数据,但有希望通过引用传递数据而不是复制。
    • std::ref可以使函数接受任何类型的引用而不仅仅是特定类型
packaged_task
  • packaged_task 简化了任务连接future & promise.
  • (TODO)

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

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

相关文章

华为AI全栈生态布局:中国科技巨头加速创新

华为AI芯片生态全栈深度分析 2024 一、引言 1.1 华为AI芯片发展背景&#xff1a; 华为&#xff0c;通信和消费电子巨头&#xff0c;以其技术创新和远见著称。2013年&#xff0c;华为率先布局人工智能&#xff08;AI&#xff09;&#xff0c;并专注于全栈AI解决方案的开发。华…

微信小程序15: 小程序组件

创建组件 ①在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建components -> test文件夹 ②在新建的components -> test文件夹上&#xff0c;鼠标右键&#xff0c;点击“新建Component‘ ③键入组件的名称之后回车&#xff0c;会自动生成组件对应的4个文件&#…

继承知识及扩展(C++)

1. 继承是什么&#xff1f; 继承是面向对象编程的三大特征之一&#xff0c;也是代码复用的手段之一。之前我们在很多的地方尝试函数的复用&#xff0c;而继承是为了类的复用提供了很好的方式。 &#xff08;1&#xff09;继承的代码怎么写 在一个类后面使用 &#xff1a;继承方…

JMeter - 如何测试REST API / 微服务

概述&#xff1a; 有许多方法和工具可用于测试REST API。 当我需要测试REST API时&#xff0c;在查看了各种工具和选项之后&#xff0c;由于以下原因&#xff0c;我选择了JMeter。 JMeter是免费和开源的。 JMeter可以从CSV文件中直接读取您的测试数据。参数化非常简单。 可以…

基于SWIFT框架的Phi-3推理、微调实战教程

近期&#xff0c; Microsoft 推出 Phi-3&#xff0c;这是 Microsoft 开发的一系列开放式 AI 模型。Phi-3 模型是一个功能强大、成本效益高的小语言模型 (SLM)&#xff0c;在各种语言、推理、编码和数学基准测试中&#xff0c;在同级别参数模型中性能表现优秀。为开发者构建生成…

零基础自学网络安全/Web安全(超详细入门到进阶)学完即可就业(含学习笔记)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

ICode国际青少年编程竞赛- Python-1级训练场-变量练习

ICode国际青少年编程竞赛- Python-1级训练场-变量练习 1、 a 8 for i in range(8):Dev.step(a)Dev.turnRight()a - 12、 a 3 for i in range(4):Dev.step(a)Dev.turnRight()a a 1 Dev.step(5)3、 a 4 for i in range(4):Dev.step(2)Dev.step(-5)Dev.step(3)Spaceship.…

一次性邮箱API发送邮件的方法?如何配置?

一次性邮箱API发送邮件有哪些注意事项&#xff1f;怎么安全发信&#xff1f; 随着网络安全问题的日益凸显&#xff0c;如何安全、高效地发送邮件成为了一个亟待解决的问题。一次性邮箱API的出现&#xff0c;为我们提供了一种新的解决方案。那么&#xff0c;如何使用一次性邮箱…

在uni-app开发的小程序中引入阿里的多色图标

uniapp不支持阿里多色图标&#xff0c;需要使用工具iconfont-tools进行处理 1.首先 在阿里图标库将 需要的图标添加到项目中 并下载压缩包&#xff0c;取出iconfont.js文件 2.安装iconfont-tools,安装完成会显示出安装到了电脑的那个目录 3&#xff0c;进入目录就会看到下面的…

【Unity动画系统】动画层级(Animation Layer)讲解与使用

如何使用Unity的Animation Layer和Avater Mask把多个动画组合使用 想让玩家持枪行走&#xff0c;但是手里只有行走和持枪站立的动作。 Unity中最方便的解决办法就是使用动画层级animation layer以及替身蒙版avatar mask。 创建一个动画层级 Weight表示权重&#xff0c;0的话则…

MFC扩展库BCGControlBar Pro v34.1 - 可视化设计器、主题新升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v34.1已正式发布了&#xff0c;这个版本包含了对Windows 10/11字体图标的支持、功能区和…

国内小白用什么方法充值使用ChatGPT4.0?

首先说一下IOS礼品卡订阅&#xff0c;目前最经济实惠的订阅方式&#xff0c;具体操作步骤 使用IOS设备充值&#xff0c;用 App Stroe 兑换券 1、支付宝地址切换旧金山&#xff0c;在里面买app store 的兑换卷 2、美区Apple ID登陆app store &#xff0c;充值兑换券 3、IOS设…

AI 数据观 | TapData Cloud + MongoDB Atlas:大模型与 RAG 技术有机结合,落地实时工单处理智能化解决方案

本篇为「AI 数据观」系列文章第二弹&#xff0c;在这里&#xff0c;我们将进一步探讨 AI 行业的数据价值。以 RAG 的智能工单应用场景为例&#xff0c;共同探索如何使用 Tapdata Cloud MongoDB Atlas 实现具备实时更新能力的向量数据库&#xff0c;为企业工单处理的智能化和自…

7款AI绘画软件推荐,必备工具,一键生成绘画

随着人工智能技术的不断发展&#xff0c;AI绘画软件在艺术创作中扮演着越来越重要的角色。这些软件利机器学习和深度学习算法&#xff0c;可以模仿艺术家的风格&#xff0c;并生成逼真的绘画作品。一起来见证下吧&#xff0c;先给大家展示下AI绘画生成的效果图&#xff1a; 一、…

边界框(bounding box) 目标物体的位置和大小 交并比(Intersection over Union,IoU) 锚框(Anchor box)

边界框(bounding box) 在检测任务中,我们需要同时预测物体的类别和位置,因此需要引入一些跟位置相关的概念。通常使用边界框(bounding box,bbox)来表示物体的位置,边界框是正好能包含物体的矩形框。 在目标检测任务中,边界框(bounding box,bbox)是一个非常重要的…

RS232/RS485转12路模拟信号隔离D/A转换器4-20mA0-20mA0-25mA0-5V0-10V0-75mV

特点&#xff1a; ● RS-485/232接口&#xff0c;隔离转换成12路标准模拟信号输出 ● 可选型输出4-20mA或0-10V控制其他设备 ● 模拟信号输出精度优于 0.2% ● 可以程控校准模块输出精度 ● 信号输出 / 通讯接口之间隔离耐压3000VDC ● 宽电源供电范围&#xff1a;10 ~ …

git与gitlab

目录 gitlab 下载与安装 重置管理员密码 gitlab命令 git远程gitlab相关命令 认证 补充 git git 分布式版本控制 安装 git的四个区域与文件的四个状态 使用git 常用命令 git 分布式管理系统 gitlab 企业私有库 github 公网共享库&#xff0c;全球…

2024五一赛数学建模ABC题成品论文word+完整代码数据汇总

2024五一赛A题参考论文42页1-3问可执行代码[py Mtlab双版本]各类可视化图表https://www.jdmm.cc/file/27105852024五一赛B题保姆级建模思路32页可执行代码[py mtlab]后续成品论文处理可视化图表https://www.jdmm.cc/file/27105862024五一赛C题成品论文23页word页1-3问可执行代码…

亚马逊自养号测评环境搭建需要准备哪些?

在当下电商领域竞争白热化的背景下&#xff0c;亚马逊平台的卖家们对流量之于店铺转化率的重要性有着深刻的认识。随着对平台内部流量的依赖逐渐减弱&#xff0c;他们纷纷寻求更多元化的途径来提升销售业绩和品牌的市场影响力。在此过程中&#xff0c;自养号测评成为了一种备受…

alphassl ocsp泛域名证书

泛域名SSL证书又可以称之为通配符SSL证书&#xff0c;这款SSL数字证书可以同时保护主域名以及主域名下的所有子域名&#xff0c;被广泛应用于各种类型的网站&#xff0c;为多个网站提供安全服务。AlphaSSL是比较知名的SSL证书品牌之一&#xff0c;旗下的OCSP泛域名SSL证书比较受…