boost::io_service::post 线程安全吗?

发布于 2024-11-16 02:18:18 字数 94 浏览 2 评论 0原文

从处理程序中发布新处理程序是线程安全的吗? 即调用 io_service::run() 的线程可以将新的处理程序发布到同一个 io_service 吗?

谢谢

Is it thread safe to post new handlers from within a handler?
I.e. Can threads that called the io_service::run() post new Handlers to the same io_service?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

青芜 2024-11-23 02:18:18

安全根据文档,从 io_service 的单个实例的处理程序中发布处理程序。

线程安全

不同的对象:安全。

共享对象:安全,但在调用reset()时除外
还有未完成的run()、run_one()、
poll() 或 poll_one() 调用结果
未定义的行为。

It is safe to post handlers from within a handler for a single instance of an io_service according to the documentation.

Thread Safety

Distinct objects: Safe.

Shared objects: Safe, with the exception that calling reset() while
there are unfinished run(), run_one(),
poll() or poll_one() calls results in
undefined behaviour.

长亭外,古道边 2024-11-23 02:18:18

我对这篇文章进行了大量编辑,请注意:原始代码有一些细微的错误,因此它似乎反驳了 ASIO 的线程安全性。我已经标记了执行后获得正确计数器 3000000 所需的更正。查看编辑历史记录以查看所做的代码更改。最重要的更新是将 service.stop() 更改为 guard.reset(),这允许 io_service 退出,一旦所有工作完成。

我选择编辑而不是发布不同的答案,因为大部分代码仍然来自原作者。由于后者在很多很多年前才活跃,而且关于他的错误的评论也很早以前就已经发表了,所以等待更长时间是没有意义的。

#include <boost/asio/io_service.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/thread.hpp>
#include <boost/thread/detail/thread_group.hpp>
#include <memory>
#include <iostream>

void postInc(boost::asio::io_service *service, std::atomic_int *counter) {
  for(int i = 0; i < 100000; i++) service->post([counter] { (*counter)++; });
}

int main(int argc, char **argv)
{
  std::atomic_int counter(0);
  
  {
    boost::asio::io_service service;
    // boost::asio::io_service::work working(service);
    auto guard = make_work_guard(service);
    boost::thread_group workers;
    
    for(size_t i = 0; i < 10;++i)     workers.create_thread(boost::bind(&boost::asio::io_service::run, &service));

    boost::thread_group producers;
    for (int it = 0; it < 30; it++)
    {
      producers.add_thread(new boost::thread(boost::bind(postInc,&service,&counter)));
    }

    producers.join_all();
    std::cout << "producers ended" << std::endl;

    // service.stop();
    guard.reset();
    workers.join_all();
  }

  std::cout << counter.load() << std::endl;

  return 0;
}

Note by me, who edited this post heavily: The original code had a few subtile bugs, so that it seemed to disproof thread-safety of ASIO. I have marked the corrections necessary to get the correct counter of 3000000 after execution. Look at the edit history to see the code changes made. The most important update is to change service.stop(), which keeps some of the posted work undone, to guard.reset(), which allows the io_service to exit, once all work has been completed.

I choose to edit instead of post a different answer, as most of the code is still from the original author. As the later was only active many, many years ago and comments about his bugs had been made long time ago, it wouldn't have made sense to wait longer.

#include <boost/asio/io_service.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/thread.hpp>
#include <boost/thread/detail/thread_group.hpp>
#include <memory>
#include <iostream>

void postInc(boost::asio::io_service *service, std::atomic_int *counter) {
  for(int i = 0; i < 100000; i++) service->post([counter] { (*counter)++; });
}

int main(int argc, char **argv)
{
  std::atomic_int counter(0);
  
  {
    boost::asio::io_service service;
    // boost::asio::io_service::work working(service);
    auto guard = make_work_guard(service);
    boost::thread_group workers;
    
    for(size_t i = 0; i < 10;++i)     workers.create_thread(boost::bind(&boost::asio::io_service::run, &service));

    boost::thread_group producers;
    for (int it = 0; it < 30; it++)
    {
      producers.add_thread(new boost::thread(boost::bind(postInc,&service,&counter)));
    }

    producers.join_all();
    std::cout << "producers ended" << std::endl;

    // service.stop();
    guard.reset();
    workers.join_all();
  }

  std::cout << counter.load() << std::endl;

  return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文