当前位置: 首页 > news >正文

并发支持库(1)-线程

线程允许多个程序任务在统一时间执行,不同的线程可以共享内存空间,每个线程也有自己的栈空间。

线程类

thread

类thread表示单个执行线程。线程在thread构造对象时开始执行。每个thread对象表示唯一的一个线程,thread不支持复制构造和复制赋值函数。

构造函数

默认的构造函数构造一个不表示任何线程的thread对象:

thread() noexcept;

构造函数可以传入一个函数并关联一个执行线程,构造完成后函数将在该线程上开始运行:

template< class F, class... Args >
explicit thread( F&& f, Args&&... args );

代码示例:

auto func = [](int index)
{for (int i = 0; i < 15; ++i){std::cout << index;std::this_thread::sleep_for(std::chrono::milliseconds(10));}
};std::thread t1(func, 1);
std::thread t2(func, 2);
t1.join();
t2.join();
std::cout << std::endl;

t1和t2分别在两个线程上同时执行,打印出来的1和2可能是交错的,可能的输出结果:

122121121212121212212121212121

析构函数

销毁thread对象时,必须合并或者分离底层线程,否则会调用std::terminate导致程序崩溃。其内部实现大致为:

~thread() noexcept 
{if (joinable()) {terminate();}
}

赋值函数

thread只支持移动赋值函数,移动后线程的所有权被转交,原thread对象不再表示任何线程。

joinable

检查线程是否可合并,如果thread代表的线程是活跃的,那么joinable返回true。代码示例:

std::cout << std::boolalpha;std::thread t;
std::cout << "t joinable: " << t.joinable() << std::endl;
t = std::thread([](){});
std::cout << "t joinable: " << t.joinable() << std::endl;
t.join();
std::cout << "t joinable: " << t.joinable() << std::endl;

输出结果:

t joinable: false
t joinable: true
t joinable: false

get_id

获取线程的id。代码示例:

std::thread t1;
std::thread t2 = std::thread([](){});
std::thread t3 = std::thread([](){});std::cout << "t1 id: " << t1.get_id() << std::endl;
std::cout << "t2 id: " << t2.get_id() << std::endl;
std::cout << "t3 id: " << t3.get_id() << std::endl;t2.join();
t3.join();

输出结果:

t1 id: 0
t2 id: 97068
t3 id: 73212

native_handle

获取底层实现的线程句柄。代码示例:

std::thread t = std::thread([](){});std::thread::native_handle_type handle = t.native_handle();
std::cout << "native handle: " << handle << std::endl;
t.join();

输出结果:

native handle: 00000000000000A8

hardware_concurrency

返回系统的逻辑处理线程数。代码示例:

auto num = std::thread::hardware_concurrency();
std::cout << "hardware concurrency: " << num << std::endl;

可能的输出结果:

hardware concurrency: 8

join

阻塞thread代表的线程直到其执行结束。代码示例:

auto Func = []()
{std::cout << "t thread" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));
};std::thread t(Func);
t.join();
std::cout << "Done " << std::endl;

输出结果:

t thread
Done

detach

将thread管理的线程从thread中分离,thread不再代表任何线程。代码示例:

auto Func = []()
{std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Func about to end" << std::endl;
};std::thread t(Func);
t.detach();
std::cout << "t detach" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));

输出结果:

t detach
Func about to end

swap、std::swap

交换两个thread管理的线程。

jthread

和thread类似,jthread管理一个执行线程。不同的是,当jthread析构时会自动合并线程。jthread内部还有一个stop_source成员(stop_source包含stop_token对象),jthread可以接受一个用stop_token作为首参数的函数用于执行线程访问,jthread有一个request_stop接口用于修改stop_token的状态,这允许执行函数根据stop_token的状态来决定是否终止函数运行。

构造函数

构造一个jthread对象并关联一个执行线程(默认构造函数不关联任何线程)。代码示例:

auto func = [](int index)
{for (int i = 0; i < 15; ++i){std::cout << index;std::this_thread::sleep_for(std::chrono::milliseconds(10));}
};std::jthread t1(func, 1);
std::jthread t2(func, 2);
t1.join();
t2.join();
std::cout << std::endl;

输出结果:

122112121212122121211212211212

析构函数

jthread对象析构时,会尝试合并其管理的执行线程,其内部实现大致为:

~jthread() 
{if (joinable()) {request_stop();join();}
}

赋值函数

jthread只支持移动赋值函数,移动后线程的所有权被转交,原jthread对象不再表示任何线程。

joinable

检查线程是否可合并,如果thread代表的线程是活跃的,那么joinable返回true。

get_id

获取线程的id。

native_handle

获取底层实现的线程句柄。

hardware_concurrency

返回系统的逻辑处理线程数。

join

阻塞thread代表的线程直到其执行结束。

detach

将jthread管理的线程从jthread中分离,jthread不再代表任何线程。

swap、std::swap

交换两个jthread管理的线程。

停止记号处理

jthread提供了get_stop_source、get_stop_token用于获取stop_source和stop_token对象,requset_stop接口用于修改stop_token状态为停止,jthread关联的执行函数可以通过其第一个参数stop_token用于其状态。代码示例:

auto Func = [](std::stop_token token)
{for (int i = 0; i < 10; ++i){if (token.stop_requested()){std::cout << i << " token stop_requested true" << std::endl;}else{std::cout << i << " token stop_requested false" << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(100));}
};std::jthread t(Func);
std::this_thread::sleep_for(std::chrono::milliseconds(350));
t.request_stop();

可能的输出结果:

0 token stop_requested false
1 token stop_requested false
2 token stop_requested false
3 token stop_requested false
4 token stop_requested true
5 token stop_requested true
6 token stop_requested true
7 token stop_requested true
8 token stop_requested true
9 token stop_requested true

注意最后一行代码

t.request_stop();

不是必须的,因为对象 t 在析构时也会调用request_stop函数。

当前线程管理函数

yield

重调度线程的执行,允许其他线程运行。具体效果依赖于编译器的实现。

get_id

返回当前线程的id。代码示例:

auto Func = []()
{std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
};std::thread t1(Func);
std::thread t2(Func);
Func();t1.join();
t2.join();

输出结果:

thread id: 22388
thread id: 79692
thread id: 85280

sleep_for

阻塞当前线程一段时间。代码示例:

auto t1 = std::chrono::system_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
auto t2 = std::chrono::system_clock::now();
std::chrono::duration<double, std::milli> time = t2 - t1;
std::cout << "time pass: " << time.count() << std::endl;

可能的输出结果:

time pass: 302.473

sleep_util

阻塞当前线程到指定的时间点。代码示例:

auto t1 = std::chrono::system_clock::now();
std::this_thread::sleep_until(t1 + std::chrono::milliseconds(400));
auto t2 = std::chrono::system_clock::now();
std::chrono::duration<double, std::milli> time = t2 - t1;
std::cout << "time pass: " << time.count() << std::endl;

可能的输出结果:

time pass: 400.504

相关文章:

并发支持库(1)-线程

线程允许多个程序任务在统一时间执行&#xff0c;不同的线程可以共享内存空间&#xff0c;每个线程也有自己的栈空间。 线程类 thread 类thread表示单个执行线程。线程在thread构造对象时开始执行。每个thread对象表示唯一的一个线程&#xff0c;thread不支持复制构造和复制…...

2024年最新阿里云服务器地域选择方法,以及可用区说明

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…...

Frida实战:Java、Native、SO层面的Hook与主动调用详解

引言 Frida是一款强大的动态代码插桩工具&#xff0c;支持对Android和iOS应用进行实时调试和注入。本文将通过实例详细解析如何在Frida中实现对Java层、Native层&#xff08;JNI&#xff09;以及.so库内函数的Hook与主动调用。 一、Hook Java层函数 首先&#xff0c;我们展示…...

Codeforces Round 883 (Div. 3)(集训队加训1)

A.如果钉子与地面距离大于绳子的长度就必须剪 #include<bits/stdc.h> #define eps 1e-5 #define INF 1e9 using namespace std; typedef long long ll; const int N 2e6 9; int a[N],b[N],cl[N]; void Lan(){int n;cin>>n;for(int i1;i<n;i){cin>>a[i]…...

自封装 bind 方法(二)

因为 bind 的使用方法是 某函数.bind(某对象&#xff0c;...剩余参数) 所以需要在 Function.prototype 上进行编程将传递的参数中的某对象和剩余参数使用 apply 的方式在一个回调函数中执行即可要在第一层获取到被绑定函数的 this&#xff0c;因为要拿到那个函数用 apply /***…...

vcomp140.dll丢失如何修复,5种修复方法轻松搞定vcomp140.dll问题

vcomp140.dll文件的丢失可能会引发一系列系统运行与软件功能上的问题。具体来说&#xff0c;这个动态链接库文件是Visual C Redistributable的一部分&#xff0c;对于许多基于此环境开发的应用程序至关重要。一旦缺失&#xff0c;可能会导致部分应用程序无法正常启动或运行&…...

计算机视觉(Computer Vision)和机器视觉(Machine Vision)

举例说明计算机视觉&#xff08;CV&#xff09;技术的优势和挑战 计算机视觉&#xff08;CV&#xff09;技术是一种使用计算机科学和机器学习方法来解释、分析和理解图像和视频的技术。它的优势和挑战如下&#xff1a; 优势&#xff1a; 高效性&#xff1a;CV技术可以快速处…...

国内用ChatGPT可以吗

PS: 无限次数&#xff0c;无需魔法&#xff0c;登录即可使用,网页打开下面 tj4.mnsfdx.net 点击跳转链接 国内用ChatGPT可以吗&#xff1f;简单来说&#xff0c;是可以的&#xff0c;国内可以使用ChatGPT。ChatGPT是一款实体机器翻译工具&#xff0c;也是一种人工智能技术&…...

数据分析-Pandas两种分组箱线图比较

数据分析-Pandas两种分组箱线图比较 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&am…...

Mac版2024 CleanMyMac X 4.14.6 核心功能详解以及永久下载和激活入口

CleanMyMac 是 macOS 上久负盛名的系统清理工具&#xff0c;2018 年&#xff0c;里程碑式版本 CleanMyMac X 正式发布。不仅仅是命名上的变化&#xff0c;焕然一新的 UI、流畅的动画也让它显得更加精致。新增的系统优化、软件更新等功能&#xff0c;使得在日常使用 macOS 时有了…...

Java引用传递及基本应用

在 Java 中&#xff0c;传递参数的方式主要有两种&#xff1a;值传递&#xff08;传递的是对象的引用值&#xff09;和引用传递。本教程将重点介绍 Java 中的引用传递以及其基本应用。 1. 引用传递概念 在 Java 中&#xff0c;所有的方法参数都是通过值传递的。对于对象类型的…...

低代码测试自动化

每个企业都希望将产品快速推向市场。虽然低代码无代码测试自动化可以帮助组织实现这一目标&#xff0c;但测试人员必须牢记几件事&#xff0c;才能通过低代码无代码来推进他们的组织。 低代码测试自动化的重要性是什么&#xff1f; 低代码测试自动化加速了测试生命周期。借助简…...

Linux 文件操作命令

1 文件与目录操作 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录cd ../.. 返回上两级目录cd - 返回上次所在目录cp file1 file2 将file1复制为file2cp -a dir1 dir2 复制一个目录 cp -a /tmp/dir1 . 复制一个…...

机器学习-面经(part8、贝叶斯和其他知识点)

机器学习面经其他系列 机器学习面经系列的其他部分如下所示&#xff1a; 机器学习-面经(part1)-初步说明 机器学习-面经(part2)-交叉验证、超参数优化、评价指标等内容 机器学习-面经(part3)-正则化、特征工程面试问题与解答合集机器学习-面经(part4)-决策树共5000字的面试问…...

图数据库 之 Neo4j - 应用场景3 - 知识图谱(8)

背景 知识图谱的复杂性:知识图谱通常包含大量的实体、关系和属性,以及它们之间的复杂关联。传统的关系型数据库在处理这种复杂性时可能面临性能和灵活性的挑战。 图数据库的优势:图数据库是一种专门用于存储和处理图结构数据的数据库。它们使用节点和边来表示实体和关系,并…...

redis 性能优化三

前言 如果Redis 没有执行大量的慢查询,同时也没有删除大量的过期的keys&#xff0c;那么我们该怎么办呢&#xff1f;那么我们是不是就应该关注影响性能的其他机制了&#xff0c;也就是文件系统和操作系统了。 Redis 会把数据持久化到磁盘&#xff0c;这个过程依赖文件系统来完…...

Python用Tkinter实现圆的半径 面积 周长 知一求二程序

Python用Tkinter实现圆的半径 面积 周长 知一求二程序 import tkinter as tk from tkinter import messagebox from tkinter import *app tk.Tk() app.title(圆的半径 面积 周长 知一求二程序) app.geometry(425x125)label1 tk.Label(app, text"半径") label2 tk.…...

电源环路补偿的目标是避免产生正反馈

在一般的认识中&#xff0c;进行电源环路设计的目的是保证电源输出端的电压稳定&#xff0c;在误差信号传入系统时&#xff0c;系统进行负反馈调节&#xff0c;矫正干扰信号带来的误差量。 那么&#xff0c;为什么要设置成这样&#xff0c;不稳定会有什么后果等等&#xff0c;…...

SSM+MySQL替换探索 openGauss对比postgresql12

SSM 介绍 SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架集由 Spring、MyBatis 两个开源框架整合而成&#xff08;SpringMVC 是 Spring 中的部分内容&#xff09;&#xff0c;常作为数据源较简单的 web 项目的框架。 Spring Spring 就像是整个项目中装配 bean 的大…...

XGboost的整理

XGboost&#xff08;extreme gradient boosting&#xff09;:高效实现了GBDT算法并进行了算法和工程上的许多改进。 XGboost的思路&#xff1a; 目标&#xff1a;建立k个回归树&#xff0c;使得树群的预测尽量接近真实值&#xff08;准确率&#xff09;而且有尽量大的泛化能力…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

在Zenodo下载文件 用到googlecolab googledrive

方法&#xff1a;Figshare/Zenodo上的数据/文件下载不下来&#xff1f;尝试利用Google Colab &#xff1a;https://zhuanlan.zhihu.com/p/1898503078782674027 参考&#xff1a; 通过Colab&谷歌云下载Figshare数据&#xff0c;超级实用&#xff01;&#xff01;&#xff0…...