C++11————线程库
thread 类的简单介绍
在 c++11 之前,涉及到多线程问题,都是和平台相关的,比如 windows 和 linux 下各自有自己的接口,这使得代码的可移植性比较差。在 c++11 中引入了线程库,使得 c++在编程时不需要依赖第三方库了
| 函数名 | 功能 |
| thread() | 构造一个线程对象,没有关联任何线程函数,即没有启动任何线程 |
| thread(fn,args1,arrgs2, ...) | 构造一个线程对象,并关联线程函数 fn,args1,args2, ... 为线程函数的参数 |
| get_id() | 获取线程 id |
| joinable() | 线程是否还在执行,joinable 代表的是一个正在执行中的线程 |
| join() | 该函数调用后会阻塞线程,当该线程结束后,主线程继续执行 |
| detach() | 在创建线程对象后马上调用,用于把被创建线程与线程对象分离开,分离的线程变成后台线程,创建线程的"死活"就与主线程无关 |
注意:
- 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态
- 当创建一个线程对象后没有提供一个线程函数,该对象实际没有对应任何线程
#include <thread>
int main()
{std::thread t1;cout << t1.get_id() << endl;return 0;
}
- 当创建一个线程对象后,并且给线程关联线程函数,该线程就被启动,与主线程一起运行,线程函数一般情况下可以有三种方式启动:函数指针,lambda 表达式,函数对象
#include <iostream>
using namespace std;
#include <thread>
void ThreadFunc(int a)
{cout << "Thread1" << a << endl;
}
class TF
{
public:void operator()(){cout << "Thread3" << endl;}
};
int main()
{// 线程函数为函数指针thread t1(ThreadFunc, 10);// 线程函数为lambda表达式thread t2([]{cout << "Thread2" << endl; });// 线程函数为函数对象TF tf;thread t3(tf);t1.join();t2.join();t3.join();cout << "Main thread!" << endl;return 0;
}
- 线程类是防拷贝的,不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即将一个线程对象关联线程的状态转移给其他线程对象,原线程对象失去对该线程的控制权,变成一个空线程,新线程对象获得该线程的控制权
#include <iostream>
#include <thread>
#include <chrono>// 一个简单的函数,用于线程执行
void do_work(int id) {std::cout << "Thread " << id << " is working." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Thread " << id << " is done." << std::endl;
}int main() {// 创建一个线程对象std::thread t1(do_work, 1); // t1 现在关联着一个执行 do_work(1) 的线程// 检查线程是否joinable,即是否有关联的线程if (t1.joinable()) {std::cout << "Thread t1 is joinable." << std::endl;}// 创建另一个线程对象,使用移动构造函数转移t1的线程控制权std::thread t2(std::move(t1)); // t1 现在是空的,t2 接管了原来 t1 的线程// 再次检查t1是否joinable,现在应该不是,因为它已经移动了if (t1.joinable()) {std::cout << "Thread t1 is joinable after move." << std::endl;} else {std::cout << "Thread t1 is not joinable after move." << std::endl;}// 等待t2关联的线程结束t2.join();// 尝试再次join t1,这将导致错误,因为t1不关联任何线程// t1.join(); // 这将抛出一个std::system_error异常return 0;
}
线程函数参数
线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,因此,即使线程参数为引用类型,在线程中修改也不能修改外部实参,因为线程参数实际引用的是线程栈的拷贝,不是外部实参
如果想要通过形参改变外部实参时,必须借助 std::ref 函数
ref 就是把参数按照引用方式传递
#include <thread>
#include <iostream>
using namespace std;void ThreadFunc1(int& x)
{x += 10;
}
int main()
{int a = 10;// 在线程函数中对a修改,不会影响外部实参,因为:线程函数参数虽然是引用方式,但其实际//引用的是线程栈中的拷贝thread t1(ThreadFunc1, a);t1.join();cout << a << endl;// 如果想要通过形参改变外部实参时,必须借助std::ref()函数thread t2(ThreadFunc1, std::ref(a));t2.join();cout << a << endl;return 0;
}
原子性操作库(atomic)
多线程最主要的问题是共享数据带来的问题(即线程安全),为此 C++11 中引入了原子操作:即不可被中断的一个或一系列操作,C++11 引入原子操作类型,使得线程间数据的同步变得非常高效
普遍的,我们可以使用 atomic 类模板,定义出需要的任意原子类型
atomic<T> t //声明一个类型为 T 的原子类型变量 t
#include <iostream>
using namespace std;
#include <thread>
#include <atomic>
atomic<size_t> sum=0;
void fun(size_t num)
{for (size_t i = 0; i < num; ++i)sum++; // 原子操作
}
int main()
{cout << "Before joining, sum = " << sum << std::endl;thread t1(fun, 1000000);thread t2(fun, 1000000);t1.join();t2.join();cout << "After joining, sum = " << sum << std::endl;return 0;
}

c++中的锁
C++11 标准库中<mutex>头文件提供了多种互斥锁类型,最常用的是 std::mutex
std::mutex mtx; // 声明一个互斥锁
mtx.lock(); // 锁定互斥锁
// 访问或修改共享数据
mtx.unlock(); // 解锁互斥锁
RAII 锁定
c++11 中引入了基于 RAII(资源获取即初始化)的锁定机制,lock_guard 和 unique_lock 是两种常用的 RAII 锁定器
lock_guard 在构造时,自动获取互斥锁,并在析构时自动释放互斥锁,适用于在一个作用域中加锁和解锁,构造线程安全的作用域
#include <mutex>
#include <iostream>void critical_section(std::mutex& mtx) {std::lock_guard<std::mutex> lock(mtx); // 自动加锁// 临界区代码std::cout << "Critical section" << std::endl;// 离开作用域时自动解锁
}int main() {std::mutex mtx;critical_section(mtx);return 0;
}
std::unique_lock 提供了对互斥锁的独占所有权,允许在构造时加锁,在析构时解锁,并且可以在对象生命周期中多次加锁和解锁
#include <mutex>
std::mutex mtx;
void function() {std::unique_lock<std::mutex> lock(mtx); // 构造时加锁// 临界区代码lock.unlock(); // 显式解锁// 非临界区代码lock.lock(); // 再次加锁// 临界区代码
} // 析构时解锁
condition_variable 条件变量

关于条件变量的一些函数
wait 函数
wait: 使当前线程在条件变量上等待,直到被另一个线程唤醒
std::unique_lock<std::mutex> lock(mtx); // 获取互斥锁
cv.wait(lock);
在这个调用中,线程会释放锁并进入等待状态,当另一个线程调用 notify_one 或 notify_all 时,等待的线程会被唤醒,并尝试重新获取互斥锁
带谓词的 wait
cv.wait(lock, []{ return some_condition; });
允许你提供一个谓词(一个返回 bool 值的函数或者 labmda 表达式),线程只有在谓词为真时才会被唤醒
notify_one 和 notify_all
cv.notify_one();//唤醒等待条件变量的一个线程
cv.notify_all();//唤醒等待条件变量的所有线程
相关文章:
C++11————线程库
thread 类的简单介绍 在 c11 之前,涉及到多线程问题,都是和平台相关的,比如 windows 和 linux 下各自有自己的接口,这使得代码的可移植性比较差。在 c11 中引入了线程库,使得 c在编程时不需要依赖第三方库了 函数名 …...
Java 动态代理初步
动态代理初步 package ReflectExercise;import ReflectExercise.pojo.BigStar; import ReflectExercise.pojo.ProxyUtil; import ReflectExercise.pojo.Star;/*** 动态代理* 无侵入的给方法增强功能*/ public class ReflectExercise {public static void main(String[] args) {…...
应用系统开发(10) 钢轨缺陷的检测系统
涡流检测系统框图 其中信号发生器为一定频率的正弦信号作为激励信号,这个激励信号同时输入给交流电桥中的两个检测线圈,将两个线圈输出的电压差值作为差分信号引出至差分放大电路进行放大,经过放大后信号变为低频的缺陷信号叠加在高频载波上…...
理解 \r、\n、\r\n 和 \n\r:换行符的区别和用法
\r(回车,Carriage Return): ASCII 码 13,对应的控制字符是 CR,将光标回到当前行的行首(而不会换到下一行),之后的输出会把之前的输出覆盖。\n(换行,Line Feed)…...
【jvm】StringTable为什么要调整
目录 1. 永久代内存限制与回收效率2. 堆内存的优势3. JDK版本的演进4. 实际应用的考虑 1. 永久代内存限制与回收效率 1.内存限制:在JDK 6及之前的版本中,StringTable位于永久代(PermGen space)中。然而,永久代的内存空…...
AI 驱动低代码平台:开创智能化用户体验新纪元
一、引言 人工智能技术如汹涌浪潮般迅猛发展,在各个行业掀起了颠覆性的变革风暴。于软件开发领域而言,AI 辅助编程与低代码平台的完美结合已然成为关键趋势,极大地提高了开发效率。然而,低代码平台的使命绝非仅仅局限于简化开发流…...
谈一谈QThread::CurrentThread和this->thread
QThread::CurrentThread是指的当前函数调用者者所在的线程 this->thread是指的当前对象所在的线程(对象创建出来的时候所在的线程) Qt文档说明 CurrentThread返回一个指向管理当前执行线程的QThread的指针 thread返回对象所在的线程 这两个函数所…...
ThriveX 博客管理系统前后端项目部署教程
前端 前端项目地址:https://github.com/LiuYuYang01/ThriveX-Blog 控制端项目地址:https://github.com/LiuYuYang01/ThriveX-Admin Vercel 首先以 Vercel 进行部署,两种方式部署都是一样的,我们以前端项目进行演示 首先我们先…...
STM32单片机设计防儿童人员误锁/滞留车内警报系统
目录 目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 1.电路图采用Altium Designer进行设计: 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 近年来在车辆逐渐普及的情况下,由于家长的疏忽,将…...
可认证数据资产合约标准协议(CMIDA-1)意见征集
标准背景 数据资产具备多维度的属性,涵盖行业特性、状态信息、资产类型、存储格式等。数据资产在不同流通主体之间可理解、可流通、可追溯、可信任的重要前提之一是存在统一的标准,缺失统一的标准,数据混乱冲突、一数多源、多样多类等问题将…...
Cyberchef配合Wireshark提取并解析HTTP/TLS流量数据包中的文件
本文将介绍一种手动的轻量级的方式,还原HTTP/TLS协议中传输的文件,为流量数据包中的文件分析提供帮助。 如果捕获的数据包中存在非文本类文件,例如png,jpg等图片文件,或者word,Excel等office文件异或是其他类型的二进…...
MYSQL- 展示事件信息 EVENTS 语句(十八)
13.7.5.18 SHOW EVENTS 语句 SHOW EVENTS[{FROM | IN} schema_name][LIKE pattern | WHERE expr]此语句显示有关事件管理器事件的信息,这些信息在第23.4节“使用事件调度器”中进行了讨论。它要求显示事件的数据库具有EVENT权限。 以最简单的形式,SHOW…...
如何在react中使用react-monaco-editor渲染出一个编辑器
一、效果展示 二、基于vite配置 1.首先安装react-monaco-editor和monaco-editor包 npm add react-monaco-editor npm i monaco-editor 2.其次创建一个单独的文件(此处是tsx、直接用app或者jsx也行) import { useState, useEffect } from react impo…...
【Linux】Github 仓库克隆速度慢/无法克隆的一种解决方法,利用 Gitee 克隆 Github 仓库
Github 经常由于 DNS 域名污染以及其他因素克隆不顺利。 一种办法是修改 hosts sudo gedit /etc/hosts加上一行 XXX.XXX.XXX.XXX github.comXXX 位置的 IP 可以通过网站查询 IP/服务器github.com的信息-站长工具 这种方法比较适合本身可以克隆,但是速度很慢的…...
HarmonyOS Next 组件或页面之间的所有通信(传参)方法总结
系列文章目录 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(上) 【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(下) 【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇(上) 【…...
单片机学习笔记 1. 点亮一个LED灯
把基础的东西都过一下,用来学习记录一下。 目录 1、Keil工程 2、Keil实现代码 3、烧录程序 0、实现的功能 点亮一个LED灯 1、Keil工程 打开Keil,Project----New uVision Project,工程文件命名----OK 选择单片机类型AT89C52,和…...
Poetry 完整安装与项目环境搭建指南
Poetry 完整安装与项目环境搭建指南 1. Poetry 安装方式 1.1 pip 安装(推荐新手使用) # 使用 pip 安装 pip install poetry# 验证安装 poetry --version# 如果需要升级 pip install --upgrade poetry1.2 官方安装脚本 # Windows PowerShell (Invoke-…...
【MyBatis源码】MapperRegistry详解
🎮 作者主页:点击 🎁 完整专栏和代码:点击 🏡 博客主页:点击 文章目录 MapperRegistry 的作用核心字段解析整体工作流程addMapper方法MapperAnnotationBuilder#parse流程详解MapperAnnotationBuilder#parse…...
Java项目实战II基于Spring Boot的工作流程管理系统设计与实现(开发文档+数据库+源码)
目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 在当今快节奏的商业环境中,…...
flink StreamGraph 构造flink任务
文章目录 背景主要步骤代码 背景 通常使用flink 提供的高级算子来编写flink 任务,对底层不是很了解,尤其是如何生成作业图的细节 下面通过构造一个有向无环图,来实际看一下 主要步骤 1.增加source 2.增加operator 3. 增加一条边࿰…...
uStepper S开源库深度解析:闭环步进控制与TMC2130驱动实战
1. uStepper S 开源驱动库深度解析:面向嵌入式工程师的实战指南 uStepper S 是一款集成了高性能步进电机驱动、高精度磁编码器反馈、ARM Cortex-M0 微控制器(NXP LPC11U35)与丰富外设接口的智能运动控制模块。其配套的 uStepper S Arduino…...
基于comsol的三相电力变压器电磁场与电路耦合计算的电压电流及磁通密度分布分析
comsol三相电力变压器电磁场和电路耦合计算,可以得到变压器高低压绕组电压电流分布以及变压器磁通密度分布三相电力变压器建模这事儿,说难不难说简单也不简单。前两天用COMSOL折腾了个带电路耦合的模型,顺手把绕组电流分布和铁芯磁通都摸清楚…...
Bedtools终极指南:基因组数据分析的完整工具集
Bedtools终极指南:基因组数据分析的完整工具集 【免费下载链接】bedtools A powerful toolset for genome arithmetic. 项目地址: https://gitcode.com/gh_mirrors/be/bedtools Bedtools是一个强大的基因组数据分析工具集,专门用于处理基因组区间…...
3步解决HEIC预览难题:面向Windows用户的高效缩略图工具
3步解决HEIC预览难题:面向Windows用户的高效缩略图工具 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 在数字影像管理中&…...
OpenPPL之二,优化器里面的算子融合
算子融合的执行时机 完整的时间线 模型加载阶段(一次) 运行时阶段(多次推理)↓ ↓ ┌─────────────────────┐ ┌─────────────┐ │ 1. 解析ON…...
Docker+iredmail搭建企业级邮件服务器全流程(附常见问题排查)
Dockeriredmail搭建企业级邮件服务器全流程指南 邮件系统作为企业日常沟通的核心基础设施,其稳定性和安全性直接影响业务运转效率。传统邮件服务器部署往往需要复杂的配置和漫长的调试周期,而Docker容器化技术结合iredmail开源邮件解决方案,为…...
2024具身智能技术全景解析:从人形机器人到AGI的硬件与算法协同进化
1. 具身智能:当机器人学会"思考"和"行动" 想象一下,你家的扫地机器人不仅能自动规划路线清洁地板,还能在你做饭时递调料瓶、在你工作疲惫时泡一杯咖啡——这不是科幻电影,而是具身智能技术正在实现的场景。具…...
聚焦数据中心基建核心:我国服务器机架导轨市场规模达8.1亿元,产业支撑力凸显
据恒州诚思最新调研数据显示,2025年全球服务器机架导轨市场规模达8.1亿元,预计至2032年将增长至11.61亿元,期间复合增长率(CAGR)为5.3%。这一增长受多重因素驱动:全球数据中心建设加速,预计2026…...
从‘深度学习之美’到TensorFlow 2.9:一个MNIST手写识别项目的实战重构记
1. 当经典教材遇上TensorFlow 2.9:我的MNIST重构历险记 记得第一次翻开《深度学习之美》这本书时,我被其中用TensorFlow实现MNIST手写识别的案例深深吸引。但当我兴冲冲打开电脑准备复现时,却发现书中的TensorFlow 1.x代码在2.9环境下几乎寸步…...
钉钉机器人Markdown表格发送实战:绕过限制的创意方案
1. 钉钉机器人Markdown表格发送的痛点与需求 很多团队都在用钉钉机器人自动推送数据报表,但官方提供的消息类型里并没有直接支持表格格式。我见过不少同事为了发个简单的数据表格,要么截图发图片(无法复制数据),要么上…...
