You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

我的Boost.Asio线程池代码是否引发死锁?请求协助排查

问题排查:Boost.Asio thread_pool偶发挂起问题

我们在开发异步微服务时使用Boost.Asio的thread_pool类提升计算吞吐量,编写的测试代码偶发挂起,疑似死锁,代码如下:

#include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/asio/use_future.hpp>

#include <cstdlib>
#include <exception>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>

int main()
{
    boost::asio::thread_pool pool{5};
    std::mutex mutex;

    for(int i = 0; i < 5; ++i)
    {
        boost::asio::post(pool, [i, &mutex]() {
            try
            {
                std::lock_guard<std::mutex> lg{mutex};
                std::cout << "Task " << i << " executed by thread " << std::this_thread::get_id()
                          << std::endl;
            }
            catch(const std::exception& e)
            {
                std::cerr << e.what() << '\n';
            }
        });
    }

    std::future<int> r1 = boost::asio::post(pool, boost::asio::use_future([]() { return 2; }));
    {
        std::lock_guard<std::mutex> lg{mutex};
        std::cout << "Result = " << r1.get() << '\n';
    }

    // Optional: Wait for all tasks to complete
    pool.join();

    return EXIT_SUCCESS;
}

问题根源:循环等待导致死锁

代码的死锁场景触发条件如下:

  • 主线程先通过std::lock_guard获取了mutex,随后调用r1.get(),阻塞等待线程池中r1对应的任务执行完成并返回结果。
  • 线程池初始化了5个线程,刚好被前5个任务占满。这5个任务都需要获取mutex才能完成执行,但此时mutex被主线程持有,所以这5个线程都处于阻塞等待锁的状态。
  • r1对应的任务被放在线程池的任务队列中,没有空闲线程可以执行它。

此时形成循环等待的死锁:

  • 主线程:持有mutex → 等待r1任务完成
  • 线程池线程:等待mutex → 无法释放线程去执行r1任务

这种场景是偶发的,因为如果r1的任务在主线程获取锁之前就被线程池执行完成,就不会触发死锁;但如果前5个任务先抢占了所有线程,就会触发挂起。

修复方案

方案1:调整锁的持有时机(推荐)

先等待r1任务完成,再获取锁输出结果,避免主线程持有锁时等待线程池任务:

std::future<int> r1 = boost::asio::post(pool, boost::asio::use_future([]() { return 2; }));
// 先等待任务完成,再获取锁输出
int result = r1.get();
{
    std::lock_guard<std::mutex> lg{mutex};
    std::cout << "Result = " << result << '\n';
}

方案2:避免主线程与线程池任务竞争同一锁

如果主线程的输出操作不需要线程安全(仅测试场景),可以直接去掉主线程的锁:

std::future<int> r1 = boost::asio::post(pool, boost::asio::use_future([]() { return 2; }));
std::cout << "Result = " << r1.get() << '\n';

方案3:增加线程池线程数(不推荐,仅降低概率)

将线程池线程数设为6,确保有空闲线程可以执行r1任务,但这只是降低死锁触发概率,无法从根本上解决问题。

内容的提问来源于stack exchange,提问作者anthonyNk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:39:59