当前位置: 首页 > 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;而且有尽量大的泛化能力…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...