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

C++ 之多线程相关总结

C++ 之多线程相关总结

1.多线程相关基础知识

1.1 线程的创建和管理

1. std::thread 类:

用于创建和管理线程。通过将可调用对象(如函数、函数对象、lambda 表达式)作为参数传递给 std::thread 的构造函数,可以创建一个新的线程。

  • join() 方法会阻塞当前线程,直到被调用的线程执行完毕。如果不调用 join()detach(),程序会在 std::thread 对象析构时终止程序,因为会调用 std::terminate()
  • detach() 方法允许线程独立运行,与主线程分离,不再被 std::thread 对象管理,它会继续在后台执行直至完成或程序结束。
#include <iostream>
#include <thread>void threadFunction() {std::cout << "Thread function running." << std::endl;
}int main() {std::thread t(threadFunction); // 创建一个新的线程,执行 threadFunctiont.join(); // 等待线程结束return 0;
}
2. 线程函数:

可以是普通函数、成员函数、函数对象或 lambda 表达式。

#include <iostream>
#include <thread>class MyClass {
public:void memberFunction() {std::cout << "Member function running in thread." << std::endl;}
};int main() {MyClass obj;std::thread t(&MyClass::memberFunction, &obj); // 调用成员函数t.join();return 0;
}

1.2 线程同步

1.互斥量(Mutex):
  • std::mutex 提供了基本的互斥机制,用于保护共享数据,防止多个线程同时访问。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;void printMessage(const std::string& message) {std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁std::cout << message << std::endl;
}int main() {std::thread t1(printMessage, "Hello from thread 1");std::thread t2(printMessage, "Hello from thread 2");t1.join();t2.join();return 0;
}
  • std::lock_guard 是一个 RAII 类,在构造时自动锁定互斥量,在析构时自动解锁,确保正确的锁定和解锁操作。
  • std::unique_lock 提供了更灵活的锁定方式,可以手动加锁、解锁,支持延迟锁定和所有权转移。
2.条件变量(Condition Variables):
  • std::condition_variable 允许线程等待某些条件的发生。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;void producer() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(100));std::unique_lock<std::mutex> lock(mtx);dataQueue.push(i);std::cout << "Produced: " << i << std::endl;cv.notify_one(); // 通知一个等待的线程}
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return!dataQueue.empty(); }); // 等待条件满足int data = dataQueue.front();dataQueue.pop();lock.unlock();std::cout << "Consumed: " << data << std::endl;if (data == 9) break;}
}int main() {std::thread t1(producer);std::thread t2(consumer);t1.join();t2.join();return 0;
}
  • cv.wait() 会释放锁并等待条件变量被通知,一旦收到通知,它会重新获取锁。
3. 原子操作
  • std::atomic 模板类提供了原子操作,确保操作的不可分割性,避免数据竞争。
#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> counter(0);void increment() {for (int i = 0; i < 1000; ++i) {++counter;}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Counter value: " << counter << std::endl;return 0;
}

1.3 线程间通信

1.共享数据:
  • 多个线程可以通过共享数据进行通信,但需要使用互斥量或其他同步机制来保护数据。
  • 避免死锁,如避免多个线程以不同顺序获取多个锁。
2.消息传递:
  • 使用 std::promisestd::future 可以实现线程间的单向消息传递。
#include <iostream>
#include <thread>
#include <future>int factorial(int n) {int result = 1;for (int i = 1; i <= n; ++i) {result *= i;}return result;
}int main() {std::promise<int> prom;std::future<int> fut = prom.get_future();std::thread t([&prom]() {int result = factorial(5);prom.set_value(result);});std::cout << "Factorial result: " << fut.get() << std::endl;t.join();return 0;
}

1.4 高级线程工具

1. std::async 和 std::future:
  • std::async 可以异步执行函数,并返回一个 std::future 对象。
#include <iostream>
#include <future>int add(int a, int b) {return a + b;
}int main() {std::future<int> result = std::async(std::launch::async, add, 3, 4);std::cout << "Sum: " << result.get() << std::endl;return 0;
}
  • std::launch::async 表示函数会在另一个线程中立即执行,std::launch::deferred 表示延迟执行,直到调用 get() 时才在调用线程中执行。
2. std::packaged_task:
  • 包装可调用对象,允许将其作为任务传递,并通过 std::future 获取结果。
#include <iostream>
#include <thread>
#include <future>int main() {std::packaged_task<int(int, int)> task(add);std::future<int> result = task.get_future();std::thread t(std::move(task), 3, 4);std::cout << "Sum: " << result.get() << std::endl;t.join();return 0;
}

2. 线程的使用:创建及管理

1.类内创建线程

  • 可以通过成员函数或者析构函数初始化或者创建线程,通过析构函数关闭/销毁线程
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>class ThreadedClass {
private:std::thread workerThread;std::atomic<bool> stopFlag;// 线程函数void workerFunction() {while (!stopFlag) {std::cout << "Thread is running..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Thread is stopping..." << std::endl;}
public:ThreadedClass() : stopFlag(false) {// 启动线程workerThread = std::thread(&ThreadedClass::workerFunction, this);}~ThreadedClass() {// 设置停止标志stopFlag = true;if (workerThread.joinable()) {// 等待线程结束workerThread.join();}}
};int main() {ThreadedClass obj;// 让程序运行一段时间,以便观察线程的行为std::this_thread::sleep_for(std::chrono::seconds(5));return 0;
}

2. 函数内部创建线程

  • 单独执行某个函数或者某个类的成员函数
#include <iostream>
#include <thread>
#include <chrono>class MyClass {
public:// 类中的函数,将在新线程中执行void classFunction() {for (int i = 0; i < 5; ++i) {std::cout << "Class function running, iteration: " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}}
};// 主函数,在其中创建线程执行类的函数
void mainFunction() {std::cout << "Main function starts." << std::endl;MyClass obj;// 创建一个新线程执行类的成员函数std::thread t(&MyClass::classFunction, &obj);// 主线程继续执行自己的任务for (int i = 0; i < 3; ++i) {std::cout << "Main function running, iteration: " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}// 等待新线程执行完毕t.join();std::cout << "Main function ends." << std::endl;
}// 函数将在新线程中执行
void newThreadFunction() {for (int i = 0; i < 5; ++i) {std::cout << "New thread: " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}
}int main() {mainFunction();//or// 创建一个新线程std::thread newThread(newThreadFunction);// 主线程继续执行自己的任务for (int i = 0; i < 3; ++i) {std::cout << "Main thread: " << i << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}// 等待新线程执行完成newThread.join();return 0;
}

----更新中。。。。。

相关文章:

C++ 之多线程相关总结

C 之多线程相关总结 1.多线程相关基础知识 1.1 线程的创建和管理 1. std::thread 类&#xff1a; 用于创建和管理线程。通过将可调用对象&#xff08;如函数、函数对象、lambda 表达式&#xff09;作为参数传递给 std::thread 的构造函数&#xff0c;可以创建一个新的线程。…...

EF Core全局查询筛选器

目录 概述 用法 添加全局查询筛选器 禁用全局查询筛选器 概述 全局查询筛选器&#xff1a;EF Core 会自动将这个查询筛选器应用于涉及这个实体类型的所有 LINQ 查询。 场景&#xff1a;软删除、多租户。 什么是软删除&#xff1f; 逻辑删除&#xff0c;并不是真正地从数…...

【开源免费】基于SpringBoot+Vue.JS欢迪迈手机商城(JAVA毕业设计)

本文项目编号 T 141 &#xff0c;文末自助获取源码 \color{red}{T141&#xff0c;文末自助获取源码} T141&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

Objective-C语言的数据库交互

Objective-C语言的数据库交互 引言 在现代应用程序开发过程中&#xff0c;数据库在数据存储和管理方面起着至关重要的作用。对于iOS应用开发者而言&#xff0c;掌握如何在Objective-C中与数据库交互显得尤为重要。本文将全面探讨Objective-C的数据库交互&#xff0c;包括SQLi…...

基于 Spring Boot 和 Vue.js 的全栈购物平台开发实践

在现代 Web 开发中&#xff0c;前后端分离的架构已经成为主流。本文将分享如何使用 Spring Boot 和 Vue.js构建一个全栈购物平台&#xff0c;涵盖从后端 API 开发到前端页面实现的完整流程。 1. 技术栈介绍 后端技术栈 JDK 1.8&#xff1a;稳定且广泛使用的 Java 版本。 Spring…...

笔记(数据运营方向)

以下是一些在工作过程中的小笔记&#xff0c;写的比较杂乱&#xff0c;后续再进行分类~ 1、掌握sql窗口函数 窗口函数又名开窗函数&#xff0c;属于分析函数的一种。用于解决复杂报表统计需求的功能强大的函数。窗口函数用于计算基于组的某种聚合值&#xff0c;它和聚合函数的…...

qt vs ios开发应用环境搭建和上架商店的记录

qt 下载链接如下 https://download.qt.io/new_archive/qt/5.14/5.14.2/qt-opensource-mac-x64-5.14.2.dmg 安装选项全勾选就行&#xff0c;这里特别说明下qt5.14.2/qml qt5.14.2对qml支持还算成熟&#xff0c;但很多特性还得qt6才行&#xff0c;这里用qt5.14.2主要是考虑到服…...

[cg] glDrawBuffers MRT的应用

glDrawBuffers 是 OpenGL 中的一个函数&#xff0c;用于指定渲染结果输出到哪些颜色缓冲区。它通常在多渲染目标&#xff08;MRT, Multiple Render Targets&#xff09;中使用&#xff0c;允许一个渲染操作同时将结果输出到多个颜色缓冲区&#xff0c;而不是默认情况下的单个颜…...

IO模型与NIO基础二

抽象基类之二 FilterInputStream FilterInputStream 的作用是用来“封装其它的输入流&#xff0c;并为它们提供额外的功能”。 它的常用的子类有BufferedInputStream和DataInputStream。 (1) BufferedInputStream的作用就是为“输入流提供缓冲功能&#xff0c;以及mark()和res…...

【设计模式】 单例模式(单例模式哪几种实现,如何保证线程安全,反射破坏单例模式)

单例模式 作用&#xff1a;单例模式的核心是保证一个类只有一个实例&#xff0c;并且提供一个访问实例的全局访问点。 实现方式优缺点饿汉式线程安全&#xff0c;调用效率高 &#xff0c;但是不能延迟加载懒汉式线程安全&#xff0c;调用效率不高&#xff0c;能延迟加载双重检…...

T-SQL语言的数据库交互

T-SQL语言的数据库交互 引言 随着信息技术的不断发展&#xff0c;数据库在各个行业中扮演着越来越重要的角色。数据库的有效管理和优化对于企业的数据安全、效率提升和决策支持至关重要。T-SQL&#xff08;Transact-SQL&#xff09;作为微软SQL Server的重要扩展语言&#xf…...

【Linux系统】Ext系列磁盘文件系统二:引入文件系统(续篇)

inode 和 block 的映射 该博文中有详细解释&#xff1a;【Linux系统】inode 和 block 的映射原理 目录与文件名 这里有几个问题&#xff1a; 问题一&#xff1a; 我们访问文件&#xff0c;都是用的文件名&#xff0c;没用过 inode 号啊&#xff1f; 之前总是说可以通过一个…...

慧集通(DataLinkX)iPaaS集成平台-业务建模之域

通过左侧导航菜单〖业务建模〗→〖域〗&#xff0c;进入该界面&#xff1b;在该界面可以查看到系统中已存在的域列表。 新建域 在慧集通平台中进入【业务建模】的【域】页面&#xff0c;点击【新建】按钮进入新建页面&#xff1b;输入编码&#xff0c;名称、模块以及对应数据类…...

【机器学习实战】kaggle 欺诈检测---使用生成对抗网络(GAN)解决欺诈数据中正负样本极度不平衡问题

【机器学习实战】kaggle 欺诈检测---如何解决欺诈数据中正负样本极度不平衡问题https://blog.csdn.net/2302_79308082/article/details/145177242 本篇文章是基于上次文章中提到的对抗生成网络&#xff0c;通过对抗生成网络生成少数类样本&#xff0c;平衡欺诈数据中正类样本极…...

android wifi framework与wpa_supplicant的交互

android frmework直接与wpa_supplicant进行交互&#xff0c;使用aidl或者hidl 二、事件 framework注册事件的地方&#xff1a; packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java class SupplicantStaIfaceCallbackImpl exte…...

初学stm32 --- flash模仿eeprom

目录 STM32内部FLASH简介 内部FLASH构成&#xff08;F1&#xff09; FLASH读写过程&#xff08;F1&#xff09; 闪存的读取 闪存的写入 内部FLASH构成&#xff08;F4 / F7 / H7&#xff09; FLASH读写过程&#xff08;F4 / F7 / H7&#xff09; 闪存的读取 闪存的写入 …...

使用C语言实现栈的插入、删除和排序操作

栈是一种后进先出(LIFO, Last In First Out)的数据结构,这意味着最后插入的元素最先被删除。在C语言中,我们可以通过数组或链表来实现栈。本文将使用数组来实现一个简单的栈,并提供插入(push)、删除(pop)以及排序(这里采用一种简单的排序方法,例如冒泡排序)的操作示…...

C语言程序环境和预处理详解

本章重点&#xff1a; 程序的翻译环境 程序的执行环境 详解&#xff1a;C语言程序的编译链接 预定义符号介绍 预处理指令 #define 宏和函数的对比 预处理操作符#和##的介绍 命令定义 预处理指令 #include 预处理指令 #undef 条件编译 程序的翻译环境和执行环…...

基于机器学习随机森林算法的个人职业预测研究

1.背景调研 随着信息技术的飞速发展&#xff0c;特别是大数据和云计算技术的广泛应用&#xff0c;各行各业都积累了大量的数据。这些数据中蕴含着丰富的信息和模式&#xff0c;为利用机器学习进行职业预测提供了可能。机器学习算法的不断进步&#xff0c;如深度学习、强化学习等…...

三种文本相似计算方法:规则、向量与大模型裁判

文本相似计算 项目背景 目前有众多工作需要评估字符串之间的相似(相关)程度&#xff1a;  比如&#xff0c;RAG 智能问答系统文本召回阶段需要计算用户文本与文本库内文本的相似分数&#xff0c;返回前TopK个候选文本。  在评估大模型生成的文本阶段&#xff0c;也需要评估…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...