0

0

如何使用c++标准库实现一个线程池? (std::future和std::promise)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-01-16 17:56:02

|

928人浏览过

|

来源于php中文网

原创

std::future和std::promise本身不构成线程池,仅用于结果传递;实现线程池需固定线程数、任务队列及同步原语,推荐用std::packaged_task封装任务并管理promise生命周期。

如何使用c++标准库实现一个线程池? (std::future和std::promise)

std::future 和 std::promise 本身不构成线程池

直接用 std::futurestd::promise 无法实现线程池——它们只是任务结果的传递机制,没有线程管理、队列调度或复用能力。你真正需要的是:一个固定数量的 std::thread 池 + 一个任务队列(如 std::queue<:function>>)+ 线程安全的同步原语(std::mutex + std::condition_variable),而 std::promise/std::future 只负责把某个任务的返回值“塞回去”。

如何让线程池支持返回值(用 std::promise)

核心思路是:每个提交的任务包装成一个闭包,该闭包接收一个 std::promise,执行完后调用 set_value()set_exception();调用方则持有对应的 std::future

  • 不能在线程池外构造 std::promise 后 move 进任务——它不可拷贝,且必须保证生命周期覆盖执行过程
  • 推荐在提交任务时就地构造 std::promise,并用 std::packaged_task 封装,它天然适配 std::function 队列,且自带 std::future
  • 如果坚持手写 promise,需确保捕获的 std::promise 是右值引用,并在任务中调用 std::move(p).set_value(...)
template
auto submit(F&& f, Args&&... args) -> std::future> {
    using R = std::invoke_result_t;
    auto p = std::make_shared>();
    auto res = p->get_future();
    auto task = [p, f = std::forward(f), ...args = std::forward(args)]() mutable {
        try {
            if constexpr (std::is_void_v) {
                std::invoke(f, args...);
                p->set_value();
            } else {
                p->set_value(std::invoke(f, args...));
            }
        } catch (...) {
            p->set_exception(std::current_exception());
        }
    };
    // 把 task 放入线程池内部队列(需线程安全)
    enqueue(std::move(task));
    return res;
}

线程池必须处理的三个关键同步点

漏掉任一都会导致死锁、竞态或资源泄漏:

Spell.tools
Spell.tools

高颜值AI内容营销创作工具

下载
  • 任务入队:用 std::mutex + std::lock_guard 保护 std::queue
  • 线程等待新任务:空闲线程用 std::condition_variable::wait() 阻塞,唤醒条件是队列非空或池被关闭
  • 池关闭流程:设标志位 → 通知所有等待线程 → 调用 join();注意不能在析构中直接 join() 若线程还在 wait,必须先 notify_all()

std::packaged_task 是比裸 std::promise 更安全的选择

它把函数对象和 promise 绑定在一起,避免手动管理 promise 生命周期,也自动处理异常传播。但要注意:

立即学习C++免费学习笔记(深入)”;

  • std::packaged_task 不可拷贝,只能 move;入队时必须用 std::move(task)
  • get_future() 返回的 std::future 只能 move 一次,重复调用会抛 std::future_error(错误码为 no_state
  • 若任务函数可能抛异常,std::packaged_task::operator() 会自动捕获并存入 future,无需额外 try/catch
template
auto submit(F&& f) -> std::future> {
    std::packaged_task()> task(std::forward(f));
    auto res = task.get_future();
    enqueue(std::move(task)); // enqueue 接收 std::function
    return res;
}
线程池最难的不是返回值封装,而是 shutdown 的时序控制:要确保所有 pending 任务被执行完、所有 worker 线程已退出、且用户持有的 std::future 不因 promise 析构而失效——这要求 promise 的生命周期至少延续到任务执行结束,而不能依赖对象。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

389

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

60

2025.12.01

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

133

2025.07.29

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

476

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

163

2023.10.07

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

298

2023.10.12

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

2

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号