用std::queue+mutex+condition_variable实现线程安全队列需加锁并配合条件变量避免忙等;std::promise与std::future配对时须确保promise生命周期覆盖任务执行,推荐用move语义移交所有权而非shared_ptr。

用 std::queue + std::mutex + std::condition_variable 实现基础队列
核心是线程安全的任务缓冲区。别直接裸用 std::queue,它不是线程安全的。每次入队/出队前必须加锁,且空队列时消费者要等待,不能忙等。
典型错误是只锁了操作但没配合条件变量——比如消费者发现 queue.empty() 就 continue,这会吃满 CPU。正确做法是用 std::condition_variable::wait() 主动挂起。
- 生产者调用
push()后,必须调用notify_one()或notify_all()唤醒至少一个消费者 - 消费者在
wait()的 lambda 中检查条件(如!queue.empty()),避免虚假唤醒 - 注意
wait()会自动释放锁,并在唤醒后重新获取——这个细节漏掉会导致死锁
用 std::promise + std::future 包装单个任务的结果
每个任务需要绑定一个“承诺”对象,让执行线程能写结果,调用方能异步读。关键在于:promise 必须在任务入队前创建,并随任务一起入队;future 交给调用方,它不参与线程同步,只是结果句柄。
常见坑是把 std::promise 放在栈上然后传进线程——一旦生产者函数返回,promise 析构,future 等待永远卡住。必须确保 promise 生命周期覆盖整个任务执行周期。
- 推荐把
std::promise<t></t>和任务函数打包成结构体(如struct Task { std::function<void> func; std::promise<int> prom; };</int></void>) - 消费者取出任务后,先执行
func(),再调用prom.set_value(result)或prom.set_exception(...) - 如果任务可能抛异常,务必捕获并用
set_exception()传递,否则未处理异常会终止线程
避免 std::shared_ptr<:promise></:promise> 引发的引用计数竞争
有人为延长 promise 生命周期,用 std::shared_ptr 包一层。但这引入新问题:多个线程可能同时访问同一个 shared_ptr 的控制块(比如生产者构造、消费者 reset、future 等待),而 shared_ptr 的引用计数操作虽原子,但大量频繁使用仍影响性能,且易掩盖真正的生命周期错误。
更稳的做法是:promise 对象本身堆分配(new std::promise<t></t>),由任务结构体独占管理,消费者执行完立即 delete;或直接用移动语义转移所有权,避免共享。
- 任务结构体定义中,promise 成员声明为
std::promise<t> prom;</t>(非指针),靠 move 构造函数移交所有权 - 入队时用
std::move(task),确保 promise 不被拷贝 - 消费者拿到 task 后,用
std::move(task.prom).get_future()是错的——get_future() 只能调用一次,且不能 move promise 之后再调用
消费者线程池里如何安全回收 future 资源
std::future 本身轻量,但它的内部状态(比如等待队列)依赖于 promise 是否已满足。如果 promise 已 set,future 可随时取值;但如果 promise 析构了还没 set,future::get() 会抛 std::future_error(错误码 no_state)。
所以消费者线程执行完任务、调用 prom.set_value() 后,promise 对象就可析构——future 侧完全不受影响。但要注意:future 对象本身若长期不调用 get() 或 wait(),不会泄漏资源,但若任务失败且没处理异常,future 会一直保持 ready 状态,只是 get() 时才抛异常。
- 调用方应尽快对 future 调用
wait()或get(),避免堆积大量 ready 状态的 future 占用内存 - 不要在多线程里反复对同一个 future 调用
get()——第二次调用会抛异常 - 若需多次查询状态,用
future.wait_for(std::chrono::seconds(0)) == std::future_status::ready
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











