C++并发以及多线程的秘密
1.基础概念
并发(Concurrency)
并发是指在同一时间段内,多个任务看起来像是同时执行的。并发并不一定意味着真正的同时执行,它可以是通过时间片轮转等方式在多个任务之间快速切换,让用户感觉多个任务在同时进行。并发可以通过多线程、多进程等方式实现。
线程(Thread)
线程是进程中的一个执行单元,是 CPU 调度和分派的基本单位。一个进程可以包含多个线程,这些线程共享进程的内存空间和系统资源,但每个线程有自己独立的栈空间和执行上下文。线程之间的通信和数据共享比进程更加方便和高效。比如,在一个浏览器进程中,可能会有负责渲染页面的线程、处理网络请求的线程等。
多线程(Multithreading)
多线程是实现并发的一种方式,它允许一个进程中同时存在多个线程,这些线程可以并行(在多核 CPU 上)或并发(在单核 CPU 上)执行不同的任务,从而提高程序的执行效率和响应速度。
进程(Process)
进程是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。每个进程都有自己独立的内存空间、系统资源(如文件描述符等)和执行上下文。不同进程之间相互独立,一个进程的崩溃通常不会影响其他进程。例如,当你打开一个浏览器、一个文本编辑器时,它们分别对应着不同的进程。(一个进程有一个主线程)
2 .操作多线程
2.1 创造线程
在 C++ 中,<thread>
库提供了用于管理线程的类和函数,它是 C++11 标准引入的,用于支持多线程编程
默认构建:
std::thread t;
带执行函数的构造函数:创建一个新线程并执行指定的函数。可以传递参数给该函数
#include <iostream>
#include <thread>void func(int a) {std::cout << "线程执行,参数: " << a << std::endl;
}int main() {std::thread t(func, 42);t.join(); // 等待线程执行完毕return 0;
}
记得 线程只能出传入右值
右值引用与线程
#include <iostream>
#include <thread>
#include <string>// 线程函数,接受一个字符串参数
void threadFunction(std::string str) {std::cout << "线程接收到的字符串: " << str << std::endl;
}int main() {// 使用右值引用传递临时对象给线程std::thread t(threadFunction, std::string("Hello, Thread!"));// 等待线程执行完毕t.join();return 0;
}
左值引用与线程
左值引用用于引用一个已经存在的对象。在多线程编程中,如果需要在线程函数中修改外部对象,或者避免对象的拷贝,可以使用左值引用
#include <iostream>
#include <thread>
#include <string>// 线程函数,接受一个字符串的左值引用
void threadFunction(std::string& str) {str += " - Modified by thread";std::cout << "线程修改后的字符串: " << str << std::endl;
}int main() {std::string message = "Initial message";// 使用左值引用传递对象给线程std::thread t(threadFunction, std::ref(message));//ref提取地址// 等待线程执行完毕t.join();std::cout << "主线程看到的修改后的字符串: " << message << std::endl;return 0;
}
因为线程只能右值传递,所有以引用形式传递对象(值传递和引用之间的区别 你可以理解为复制和对地址操作)关于右值的话:c++新特性之 左右值 lambda 以及“for”-CSDN博客
成员函数
普通:
#include <iostream>
#include <thread>class MyClass {
public:// 普通成员函数void memberFunction(int value) {std::cout << "线程正在执行成员函数,传入的值是: " << value << std::endl;}
};int main() {MyClass obj;int param = 42;// 创建线程并引用类的普通成员函数std::thread t(&MyClass::memberFunction, &obj, param);// 等待线程执行完毕t.join();return 0;
}
静态:
#include <iostream>
#include <thread>class MyClass {
public:// 普通成员函数void memberFunction(int value) {std::cout << "线程正在执行成员函数,传入的值是: " << value << std::endl;}
};int main() {MyClass obj;int param = 42;// 创建线程并引用类的普通成员函数std::thread t(&MyClass::memberFunction, &obj, param);// 等待线程执行完毕t.join();return 0;
}
2.2成员函数
join函数
join()
函数的作用是阻塞当前线程,直到被调用 join()
的 std::thread
对象所代表的线程执行完毕。也就是说,当在一个线程(通常是主线程)中调用另一个线程对象的 join()
方法时,当前线程会暂停执行,等待目标线程执行结束后才会继续执行后续代码。
#include <iostream>
#include <thread>// 线程函数
void threadFunction() {for (int i = 0; i < 5; ++i) {std::cout << "子线程输出: " << i << std::endl;}
}int main() {std::thread t(threadFunction);std::cout << "主线程等待子线程执行完毕..." << std::endl;t.join(); // 主线程阻塞,等待子线程执行完毕std::cout << "子线程执行完毕,主线程继续执行。" << std::endl;return 0;
}
detch 函数
detach()
函数用于将 std::thread
对象所代表的线程与该对象分离,让线程在后台独立执行。分离后的线程在执行完毕后会自动释放资源,而不需要主线程调用 join()
来等待它结束。一旦线程被分离,就无法再通过 join()
来等待它,也不能再使用该 std::thread
对象来管理这个线程。
#include <iostream>
#include <thread>
#include <chrono>// 线程函数
void detachedThreadFunction() {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "分离的线程执行完毕。" << std::endl;
}int main() {std::thread t(detachedThreadFunction);std::cout << "主线程不等待分离的线程,继续执行。" << std::endl;t.detach(); // 分离线程std::cout << "主线程继续执行其他任务..." << std::endl;// 主线程可以继续执行其他任务,不需要等待分离的线程return 0;
}
2.3detach陷阱
你考虑一下 上面是不是陷入陷阱?
应该是的 因为
#include <iostream>
#include <thread>
#include <chrono>// 线程函数
void detachedThreadFunction() {std::this_thread::sleep_for(std::chrono::seconds(2));//等待2s才进行std::cout << "分离的线程执行完毕。" << std::endl;
}int main() {std::thread t(detachedThreadFunction);std::cout << "主线程不等待分离的线程,继续执行。" << std::endl;t.detach(); // 分离线程std::cout << "主线程继续执行其他任务..." << std::endl;// 让主线程等待足够长的时间,确保分离的线程执行完毕std::this_thread::sleep_for(std::chrono::seconds(3)); return 0;
}
你会发现主线程已经结束了
2.4 异步执行的特性
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>void threadFunction(int id) {// 模拟线程的工作负载int i=id;if (id%2==0)id=id*3;std::this_thread::sleep_for(std::chrono::seconds(id));std::cout << "Thread " << i << " finished its work." << std::endl;
}int main() {const int numThreads = 5;std::vector<std::thread> threads;// 创建多个线程for (int i = 0; i < numThreads; ++i) {threads.emplace_back(threadFunction, i + 1);}// 等待所有线程完成for (auto& thread : threads) {thread.join();}std::cout << "All threads have finished." << std::endl;return 0;
}
//就会清晰的发现 结果
Thread 1 finished its work.
Thread 3 finished its work.
Thread 5 finished its work.
Thread 2 finished its work.
Thread 4 finished its work.
windows按工作时间来的,不是按顺序!!!
相关文章:
C++并发以及多线程的秘密
1.基础概念 并发(Concurrency) 并发是指在同一时间段内,多个任务看起来像是同时执行的。并发并不一定意味着真正的同时执行,它可以是通过时间片轮转等方式在多个任务之间快速切换,让用户感觉多个任务在同时进行。并发…...

自学微信小程序的第十二天
DAY12 1、腾讯地图SDK是一套为开发者提供多种地理位置服务的工具,可以使开发者在自己的应用中加入地图相关功能,轻松访问腾讯地图服务和数据,更好地实现微信小程序的地图功能。 表49:search()方法的常用选项 选项 类型 说明 keyword string POI搜索关键词,默认周边搜索 l…...
⭐算法OJ⭐跳跃游戏【贪心算法】(C++实现)Jump Game 系列 I,II
既股票买卖系列之后的第二组贪心算法题目:跳跃游戏系列。这一篇介绍的两个问题,其输入均为一个数组,每个元素表示在该位置可以跳跃的最大长度。 55. Jump Game You are given an integer array nums. You are initially positioned at the …...

带你从入门到精通——自然语言处理(五. Transformer中的自注意力机制和输入部分)
建议先阅读我之前的博客,掌握一定的自然语言处理前置知识后再阅读本文,链接如下: 带你从入门到精通——自然语言处理(一. 文本的基本预处理方法和张量表示)-CSDN博客 带你从入门到精通——自然语言处理(二…...

ubuntu挂载固态硬盘
Ubuntu 中挂载位于 /dev/sdc1 的固态硬盘,可以按照以下步骤操作: 步骤 1:确认分区信息 首先,确保设备 /dev/sdc1 存在且已正确分区: sudo fdisk -l /dev/sdc # 查看分区表 lsblk # 确认分区路…...

WPF+WebView 基础
1、基于.NET8,通过NuGet添加Microsoft.Web.WebView2。 2、MainWindow.xaml代码如下。 <Window x:Class"Demo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/win…...

国内光子AI智能引擎:OptoChat AI在南京江北新区亮相
3月3日,从南京市投资促进局传来振奋人心的消息,南京江北新区的一家高科技企业——南京南智先进光电集成技术研究院有限公司(简称“南智光电”),携手南京知满科技等合作伙伴,成功研发出国内首个光子AI智能引…...

vscode离线配置远程服务器
目录 一、前提 二、方法 2.1 查看vscode的commit_id 2.2 下载linux服务器安装包 2.3 安装包上传到远程服务器,并进行文件解压缩 三、常见错误 Failed to set up socket for dynamic port forward to remote port(vscode报错解决方法)-C…...
【安装】SQL Server 2005 安装及安装包
安装包 SQLEXPR.EXE:SQL Server 服务SQLServer2005_SSMSEE.msi:数据库管理工具,可以创建数据库,执行脚本等。SQLServer2005_SSMSEE_x64.msi:同上。这个是 64 位操作系统。 下载地址 https://www.microsoft.com/zh-c…...

使用Maven搭建Spring Boot框架
文章目录 前言1.环境准备2.创建SpringBoot项目3.配置Maven3.1 pom.xml文件3.2 添加其他依赖 4. 编写代码4.1 启动类4.2 控制器4.3 配置文件 5.运行项目6.打包与部署6.1 打包6.2 运行JAR文件 7.总结 前言 Spring Boot 是一个用于快速构建 Spring 应用程序的框架,它简…...

将docker容器打包为.tar包
1. 创建打包脚本 #!/bin/bash # 设置 -e 使得脚本在遇到错误时停止执行 set -e# 必要的参数 exported_container_name"needed_export_container_name_or_id" # 需要被导出的容器的名称或id image_save_name"my_custom_image_name:v25.03.03" # 镜像需…...

SYSTEM文件夹下的文件
sys文件夹下的.c和.h文件里的函数 最重要的倒数第二个 deley文件夹下的.c和.h文件 Systick工作原理 系统滴答定时器是在内核里的 每来一个时钟信号,计数器减一 F1系列时钟源是HCLK(就是AHB总线上的时钟信号) Systick控制寄存器 Systick重装…...

GPPT: Graph Pre-training and Prompt Tuning to Generalize Graph Neural Networks
GPPT: Graph Pre-training and Prompt Tuning to Generalize Graph Neural Networks KDD22 推荐指数:#paper/⭐⭐# 动机 本文探讨了图神经网络(GNN)在迁移学习中“预训练-微调”框架的局限性及改进方向。现有方法通过预训练(…...

【SegRNN 源码理解】PMF的多步并行预测
位置编码 elif self.dec_way "pmf":if self.channel_id:# m,d//2 -> 1,m,d//2 -> c,m,d//2# c,d//2 -> c,1,d//2 -> c,m,d//2# c,m,d -> cm,1,d -> bcm, 1, dpos_emb torch.cat([self.pos_emb.unsqueeze(0).repeat(self.enc_in, 1, 1),self.cha…...
构建自己的AI客服【根据用户输入生成EL表达式】
要实现一个基于对话形式的AI客服系统,该系统能够提示用户输入必要的信息,并根据用户的输入生成相应的EL(Expression Language)表达式编排规则,您可以按照以下步骤进行设计和开发。本文将涵盖系统架构设计、关键技术选型…...

(50)[HGAME 2023 week2]before_main
[HGAME 2023 week2]before_main nss:3501 我们进入那个sub_12EB然后我们发现这个就是base64加密 我们取得qword_4020: 0CxWsOemvJq4zdk2V6QlArj9wnHbt1NfEX/3DhyPoBRLY8pK5FciZau7UMIgTSG 很显然这个是自定义映射base64.然后我们代入我们之前写的base64自定义映射代码 enc:A…...
机器学习数学基础:39.样本和隐含和残差协方差矩阵
假设我们研究学生的数学成绩、英语成绩和学习时间之间的关系。收集了100名学生这三项数据作为样本。 样本协方差矩阵 计算得到的样本协方差矩阵如下(假设数据简化): [ V a r ( 数学 ) C o v ( 数学 , 英语 ) C o v ( 数学 , 学习时间 ) C …...
java之http传MultipartFile文件
【需求】前端请求后端做文件上传或者excel上传,后端不解析直接把MultipartFile传给第三方平台,通过http的方式该怎么写 import org.springframework.web.multipart.MultipartFile;import java.io.*; import java.net.HttpURLConnection; import java.ne…...
深入解析SpringMVC中Http响应的实现机制
在Web应用开发中,处理HTTP请求并返回相应的HTTP响应是核心任务之一。SpringMVC作为Java生态中广泛使用的Web框架,提供了灵活且强大的机制来处理HTTP请求和生成HTTP响应。本文将深入探讨SpringMVC中如何实现HTTP响应的返回,涵盖从控制器方法的…...
构建一个支持精度、范围和负数的-Vue-数字输入框
分析并实现一个支持精度、范围和负数控制的数字输入框。 背景 在很多业务中,我们经常需要使用数字输入框,通常这些输入框会涉及到数字校验,比如限制输入范围、设置小数精度、是否允许负数等。每次写表单时,都需要重复定义这些校…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...

相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...