使用 asio 提升线程池:线程随机不执行

Posted

技术标签:

【中文标题】使用 asio 提升线程池:线程随机不执行【英文标题】:Boost threadpool using asio: Threads randomly don't execute 【发布时间】:2013-12-17 12:54:09 【问题描述】:

我正在使用基于boost::asio::ioservice 的线程池。但是,线程有时不会执行发布到 ioService 的工作。

我构建了以下最小示例来调查此问题:

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <iostream>

#include "threadpool.h"

int fib(int x) 
    if (x == 0) return 0;
    if (x == 1) return 1;
    return fib(x-1)+fib(x-2);


void doSomething(int value)

  std::cout << "doSomething(): " << fib(value) << std::endl;


void doSomethingElse(int value)

  std::cout << "doSomethingElse(): " << value+value << std::endl;


int main(int argc, char** argv)

  // create asio ioservice and threadgroup for the pool
  boost::asio::io_service ioService;
  boost::thread_group threadpool;

  // Add worker threads to threadpool
  for(int i = 0; i < 5; ++i)
  
    threadpool.create_thread(
      boost::bind(&boost::asio::io_service::run, &ioService));  
  

  // post work to the ioservice
  ioService.post(boost::bind(doSomething, 40));
  ioService.post(boost::bind(doSomethingElse, 3));

  // run the tasks and return, if all queued work is finished
  ioService.run();

  // join all threads of the group
  threadpool.join_all();

如果我像这样在循环中运行它:

while true; do echo "--------------"; ./boost_threadpool_test; done

我会得到类似这样的输出:

--------------
doSomething(): 102334155
doSomethingElse(): 6
--------------
--------------
--------------
--------------
doSomething(): 102334155
doSomethingElse(): 6
--------------
--------------
--------------
doSomething(): 102334155
doSomethingElse(): 6
--------------
--------------
doSomething(): 102334155
doSomethingElse(): 6
--------------
--------------
--------------
--------------
--------------
--------------
doSomething(): 102334155
doSomethingElse(): 6
--------------

所以连续 2 行或更多行表明线程尚未处理它们的工作。 我还尝试了自己的线程池实现,仅使用 boost 线程组来切断 IOService,但结果相似。 我在这里有什么基本的错误吗?

顺便说一句:我正在使用 Boost 1.46.1

【问题讨论】:

【参考方案1】:

你打电话给io_service::run(),但不要把any work给io_service,所以run()just exits。现在你必须在任何后续的run() 之前调用io_service::reset()

它有时会起作用的事实是由于竞争条件:ioService.post(boost::bind(doSomething, 40)) 可能会在池中的线​​程启动之前的片刻在主线程中执行,从而给 io_service 一些工作。

【讨论】:

【参考方案2】:

你应该读一遍,再读一遍,that post来自Tanner Sansbury,他是一个asio老板!

asio 没有那么复杂,但只有一次才能完全理解这个基本行为。

欢迎来到 asio 的精彩世界!

【讨论】:

以上是关于使用 asio 提升线程池:线程随机不执行的主要内容,如果未能解决你的问题,请参考以下文章

Boost.Asio 是不是可以使用单独的线程进行读写?

如何让提升池访问 gsl 矩阵以线程化任务

使用 boost::asio::thread_pool 的 C++ 线程池,为啥我不能重用我的线程?

使用 boost 创建线程池

多线程和Boost::Asio

进程池和线程池