C++并发编程之五 高级线程管理

C++多线程并发(一)--- 线程创建与管理 一、何为并发 简单来说,并发指的是两个或多个独立的活动在同一时段内交替发生。与并发相近的另一个概念是并行,并行则强调的是多个独立的活动在同一时刻点同时发生。 二、为什么使用并发 在应用程序中使用并发的原因主要有两个:关注点分离和性能。事实上,甚至可以说它们差不多是使用并发的唯一原因;当你观察的足够仔细时,一切其他因素都可以归结到这两者之一(或者可能是二者兼有)。 阅读详情

文章目录

5.1.1 线程池

在前面我们引入了线程的通信和同步手段,那么为什么还要引入线程池呢?
线程池是一种管理多个线程的技术,它可以减少线程的创建和销毁的开销,提高并发性能。线程池中有一定数量的空闲线程,当有新的任务到来时,就从池中分配一个线程来执行任务,当任务完成后,线程返回池中等待下一个任务。这样可以避免频繁地创建和销毁线程,节省资源和时间。

用C++11实现线程池的基本思路是:

  1. 创建一个任务队列,用来存放用户提交的任务。
  2. 创建一个线程队列,用来存放一定数量的空闲线程。
  3. 使用互斥锁和条件变量来同步任务队列和线程队列的访问。
  4. 当有新的任务到来时,将任务放入任务队列,并通知一个空闲线程去执行它。
  5. 当一个线程完成了任务后,将自己放回线程队列,并等待下一个任务。
  6. 当用户想要停止线程池时,向所有线程发送停止信号,并等待它们结束。

下面是一个简单的示例代码:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>

class ThreadPool {
public:
    // 构造函数,创建指定数量的线程
    ThreadPool(size_t num_threads) : stop(false) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers.emplace_back([this]() {
                while (true) {
                    std::function<void()> task;
                    // 从任务队列中取出一个任务
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        this->condition.wait(lock, [this]() { return this->stop || !this->tasks.empty(); });
                        if (this->stop && this->tasks.empty()) return;
                        task = std::move(this->tasks.front());
                        this->tasks.pop();
                    }
                    // 执行这个任务
                    task();
                }
            });
        }
    }

    // 向任务队列中添加一个新的任务
    template<class F, class... Args>
    void enqueue(F&& f, Args&&... args) {
        std::function<void()> task = std::bind(std::forward<F>(f), std::forward<Args>(args)...); 
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            tasks.emplace(task);
        }
        condition.notify_one();
    }

    // 停止所有线程并回收资源
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread& worker : workers) worker.join();
    }

private:
    std::vector<std::thread> workers; // 线程队列
    std::queue<std::function<void()>> tasks; // 任务队列

    std::mutex queue_mutex; // 互斥锁
    std::condition_variable condition; // 条件变量

    bool stop; // 停止标志
};

// 测试函数,打印一些信息
void print(int i) {
    std::cout << "Hello from thread " << i << "\n";
}

int main() {
    ThreadPool pool(4); // 创建4个线程的线程池

    for (int i = 0; i < 10; ++i) pool.enqueue(print, i); // 添加10个测试任务

}
  1. bar(std::forward<Args>(args)…) 中的 … 是函数参数包展开语法,它会将 args中的每个参数展开成一个单独的函数参数。这意味着,如果 args是一个包含多个参数的参数包,那么这个展开语法将会在函数调用时展开成多个函数参数。
  2. 例如,假设 args 包含两个参数,一个 int 和一个 double,那么bar(std::forward(args)…) 将会被展开成 bar(std::forward(arg1), std::forward(arg2)),其中 arg1 和 arg2 分别代表参数包中的第一个参数和第二个参数。
  3. 因此,使用函数参数包展开语法可以将参数包中的参数展开成多个单独的函数参数,从而使得参数可以被正确地转发给其他函数或进行其他操作。
  4. 在展开语法中,…符号前面的内容是函数模板中的参数包名称(例如:T),而…符号本身是展开语法符号,用于告诉编译器要将参数包展开成一系列参数,并将它们传递给函数func。
  5. 在这个例子中,逗号操作符不是必需的,因为参数包展开符号已经足够明确地告诉编译器要将参数包展开成一系列参数。
「C/C++」C++多线程 之 并发编程 C++通过其强大的标准库和灵活的语法特性,为并发编程提供了丰富的工具和手段。从基本的线程管理到高级的并行算法,再到异步编程的支持,C++都能满足不同的并发处理需求。然而,并发编程也带来了复杂性,开发者需要深入理解同步机制、线程安全等问题,以确保程序的正确性和性能。通过合理的设计和实践,C++并发编程可以极大地提升程序的执行效率和响应能力。何曾参静谧的博客。 阅读详情

相关推荐

C++并发编程完全指南:从基础到实践

在当今多核处理器普及的时代,充分利用硬件并发能力已成为高性能编程的关键。C++11引入的现代并发编程支持使得开发者能够以标准化、可移植的方式编写多线程程序。本文将全面介绍C++并发编程的各个方面,从基础概念到实际应用,帮助您掌握这一重要技能。

vvilkin的学习备忘 2195

C++11 线程池:轻量级高并发解决方案

基于C++11的特性 ,实现线程池 ,感受C++11的魅力。

qq_62989250的博客 825

【C++】并发编程

一、线程创建与管理 1.1 并发 1.1.1 并发与并行 并发:同一时间段内可以交替处理多个操作,强调同一时段内交替发生。 并行:同一时刻内同时处理多个操作,强调同一时刻点同时发生。 1.1.2 硬件并发与任务切换 单片机上的单核处理器支持并发多任务处理,依靠任务切换实现,与多核处理器上的多任务并发处理方式不同。 双核处理器并行执行(硬件并发)对比单核处理器并发执行(任务上下文切换) 双核处理器均并发执行(一般任务数远大于处理器核心数,多核并发更常见) 1.1.3 多线程并发与多进程并发 任务

踏雪寻梅 2861

C++并发:高级线程管理

将可同时执行的任务都提交给线程池,再将其放入任务队列中等待,随后,任务队列中的任务分别由某一工作线程领取,执行完后,该线程再从队列中取出另一任务来执行,如此循环反复。线程池的构建设计好几项关键的设计议题:包括使用多少个线程为线程分配任务的最有效方法,以及等待任务完成与否等。

FranYeCisco的博客 228

【NVIDIA驱动的顽固问题】---- /dev/sdax:clean,xxx/xxx files,xxx/xxx blocks ---- 最全解决方法

本文的意义在于整理总结关于此问题的全部解决方法,希望能给大家节约时间。

lc1852109的博客 3127

Gradle进阶:4:结合Sonarqube进行代码审查

作为代码质量检查的流行工具,比如Sonarqube能够检查代码的“七宗罪”,跟代码结合起来能够更好地提高代码的质量,这篇文章将会介绍如何结合gradle和sonarqube对代码质量与测试覆盖率进行分析。

知行合一 止于至善 1万+

第九章 高级线程管理

文章目录9.1 线程池9.1.1 最简单的线程池 9.1 线程池 将每个任务指定给某个线程是不切实际的,不过可以利用现有的线程,进行并发执行。线程池就提供了这样的功能,提交到线程池中的任务将并发执行,未提交的任务将会挂在任务队列上。队列中的每一个任务都会被池中的工作线程所获取,当任务执行完成后,再回到线程池中获取下一个任务 创建一个线程池时,会遇到几个关键性的设计问题,比如:可使用的线程数量,高...

Echo_dia的博客 240

STM32F407+LAN8720网口不通?别慌,手把手教你用CubeMX和LWIP搞定RMII以太网(附复位与PHY地址避坑指南)

本文详细解析了STM32F407与LAN8720通过RMII接口实现以太网通信的完整流程,重点解决了网口不通的常见问题。从硬件连接到CubeMX配置,再到LWIP网络参数设置,提供了复位时序、PHY地址配置等关键细节的避坑指南,帮助开发者快速排查和解决以太网通信故障。

weixin_33695082的博客 419

C++线程管理简述

我在学C++线程管理的时候学了发现C++有很多可以帮助管理线程的类 做个整理std::mutex互斥量类, 最基本的一个类, 实例化std::mutext就会产生一个互斥量, 调用成员函数lock和unlock 就可以上锁, 去锁, 很方便, 但是还不够, 我们需要手动的去设置mutex的锁和不锁, 这个很简单就像PV原语一样, 代码如下void critical_zone(string mess

Catelemmon的博客 1214

别再为调试发愁!STM32CubeMX+FreeRTOS下,串口printf打印的保姆级配置指南(基于STM32F429)

本文详细介绍了在STM32CubeMX和FreeRTOS环境下实现稳定串口printf打印的配置方法。通过硬件选型、基础配置、线程安全的重定向实现以及高级调试技巧,帮助开发者解决多任务环境下的串口输出问题,提升调试效率。特别适用于STM32F429开发板用户。

weixin_42527401的博客 273

超声波 vs 红外 vs 激光雷达:扫地机器人避障传感器选型指南(实测对比)

本文深入对比了扫地机器人三种主流避障传感器——超声波、红外与激光雷达的核心原理与实测表现。文章基于成本、精度、环境适应性等关键指标,提供了清晰的选型决策树和典型场景配置方案,旨在帮助开发者与爱好者根据项目需求与预算,构建高效可靠的机器人避障系统。

h0i1j2k3l的博客 690

C++并发编程之五 高级线程管理_c++高级实现线程管理器

线程池是一种管理多个线程的技术,它可以减少线程的创建和销毁的开销,提高并发性能。线程池中有一定数量的空闲线程,当有新的任务到来时,就从池中分配一个线程来执行任务,当任务完成后,线程返回池中等待下一个任务。这样可以避免频繁地创建和销毁线程,节省资源和时间。在前面我们引入了线程的通信和同步手段,那么为什么还要引入线程池呢?

2501_90257184的博客 269

手把手教你用TUSB2E22中继器实现eUSB2与USB 2.0互转(附实测数据对比)

本文详细介绍了如何利用TUSB2E22中继器实现eUSB2与USB 2.0的高效互转,包括技术背景、硬件设计要点、信号完整性测试方法及故障排查策略。通过实测数据对比,展示了TUSB2E22在信号延迟、功耗和眼图性能上的显著优势,为工程师提供了实用的工程方案。

weixin_29199873的博客 283

C C++最新C++并发编程之五 高级线程管理_c++高级实现线程管理器,带你全面理解View的绘制流程

【代码】C C++最新C++并发编程之五 高级线程管理_c++高级实现线程管理器,带你全面理解View的绘制流程。

2401_84975411的博客 294

移远EC800M CAT1模块HTTP POST实战:从AT指令到OneNet平台数据上报(附STM32代码)

本文详细介绍了移远EC800M CAT1模块通过AT指令实现HTTP POST数据上报到OneNet平台的完整流程,包含STM32实战代码。内容涵盖PDP上下文激活、HTTP服务配置、JSON数据包构建等关键技术要点,并提供硬件连接、状态机设计和错误处理等实用方案,助力开发者快速实现物联网设备稳定数据传输。

weixin_42565652的博客 507

验证 helm Chart 的正确性

验证 helm Chart 的正确性

小橙子的笔记屋 281

C++并发编程:线程与同步的艺术

本文介绍了C++并发编程的核心概念与实践方法。主要内容包括:线程的创建与管理(基本使用、属性设置、错误处理);互斥锁的应用(基本使用、死锁预防);以及条件变量的同步机制。通过代码示例演示了如何实现线程间的安全通信与资源同步,帮助开发者掌握高效、安全的多线程编程技术。文章涵盖了从基础概念到实际应用的全过程,适合希望提升并发编程能力的C++开发者学习参考。

编程世界如山海,探索不止。 2万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Multithreading-Cpp-Course:掌握现代C++并发编程的不二选择

Multithreading-Cpp-Course:掌握现代C++并发编程的不二选择 项目介绍 在现代软件开发领域,多线程编程是一个至关重要的技能。它不仅能提升程序的性能和响应速度,还能有效利用多核处理器的能力。Multithreading-Cpp-Course 是一套针对现代C++并发编程的教程源码,源自知名的在线教育平台Udemy上的课程 "Learn Multithreading ...

gitblog_01108的博客 705

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

线程纵横:C++并发编程的深度解析与实践

在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的 线程,必须包含< thread >头文件。常见线程函数简介:用于创建和管理的线程对象。通过构造函数启动线程,并将一个可调用对象(如函数、Lambda表达式、函数对象)作为参数传递给线程。返回当前线程的ID。

weixin_73951752的博客 1961

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C++并发编程实战读书笔记——线程管理

并发的两种途径:多个进程,每个进程只有一个线程(multiple single-threaded processes);每个进程有多个线程(multiple threads in a single process)。多个单线程/进程的启动和通信开销要比单一进程多线程间的启动和通信大。若不考虑共享内存可能带来的问题,多线程是主流语言(包括C++)更青睐的并发途径。此外,C++标准并未对进程间通信提供...

肥叔菌的博客 8817

C++并发编程 -1.线程管理

本栏主要介绍《C++并发实战编程》这本书,。将按照书目录分为 九章节介绍C++并发编程,尽可能简化本书内晦涩难懂知识点。本章节主要讲解线程使用基础。详细介绍线程使用基础(线程发起、等待、参数、异常处理)、线程管控(归属权、并发数量等)。

qq_45604814的博客 1170

C++并发编程:线程、同步与异步的艺术

本文介绍了C++并发编程的核心概念和技术。主要内容包括:并发与并行的区别、线程创建与管理、同步机制(互斥锁、条件变量、原子操作)以及异步编程(future和promise)。通过代码示例演示了线程安全操作、线程间通信和异步任务处理的方法。文章旨在帮助开发者掌握并发编程思维,设计高效且线程安全的代码,提升多线程应用的性能和可靠性。

编程世界如山海,探索不止。 1万+

C++的线程管理

这些提供者中的每一个(要么是promise或packaged_task对象,要么是对async的调用)与未来对象共享对共享状态的访问:提供者使共享状态准备就绪的点与未来对象访问共享状态的点同步状态。函数模板 std::async 异步运行函数 f ,可能在一个单独的线程中,该线程可能是线程池的一部分,并返回一个 std::future ,它最终将保存该函数调用的结果。默认构造的(未初始化的)线程对象是不可连接的,并且它的线程 id 对于所有不可连接的线程都是通用的。future 对象仅在有效时才有用。

IT_Beijing_BIT的博客 2062

C++并发编程实战(二):线程管理

一旦线程完成并且join()返回后,std::thread对象将不再关联任何线程,因此不能再次调用join()。如果std::thread对象在其析构之前没有被join()或detach(),那么析构函数会调用std::terminate()终止程序。因此,必须确保在线程对象销毁之前,要么join()要么detach()。如果std::thread对象没有关联任何执行线程(例如,它已经被join()或detach()),则get_id()将返回默认构造的std::thread::id值,表示“没有线程”。

_ 1199

C++并发编程:线程池学习

类模版 std::function 是一种通用、多态的函数封装,可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等std::function 对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)

qq_45797625的博客 2044

C++并发编程 - 线程管理

我们的对象就是在创建的时候方才执行函数,而不是使用某一个类似于run的API执行。这使得我们启动一个线程的方式变得很简单:// A demo我们这样就派生出了一个执行流task。出于C++语法解析的原因,有的时候我们会遇上定义-声明混淆的问题。比如说假使我们传递了一个自己定义的仿函数:​int main()MyTask t;这里会被认为是声明了一个带有一个参数,返回值是std::thread的名称是task的函数。

charlie114514191的博客 1086
上一篇: C++编程之 可变参数模板
下一篇: CMake项目实战指令详细分析
ZHAOCHENHAO-
博客等级 码龄10年 2774粉丝 72原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值