当一个线程将计时器添加到boost :: asio :: io_service并且另一个线程同时运行io_service :: run时,它是否是线程安全的?

时间:2012-04-07 02:50:40

标签: c++ boost thread-safety boost-asio

长话短说,我的代码:

#include <iostream>
#include <map>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace ba = boost::asio;
namespace bp = boost::posix_time;

typedef std::map<int, ba::deadline_timer*> timer_map;

timer_map g_timers;
boost::mutex g_timers_lock;

ba::io_service g_ios;

void on_timer(int id) {
    {
            boost::mutex::scoped_lock lock(g_timers_lock);
            timer_map::iterator it = g_timers.find(id);
            assert(it != g_timers.end());
            g_timers.erase(id);
    }

    // std::cout << "delete timer " << id << std::endl;
}

int main(void) {
    boost::thread trd(boost::bind(&ba::io_service::run, &g_ios));
    trd.detach();

    int count = 0;
    for (;;) {
            for (int i = 0; i < 100; i++) {
                    ba::deadline_timer* pt = new ba::deadline_timer(g_ios, bp::seconds(1));
                    pt->async_wait(boost::bind(&on_timer, count));

                    boost::mutex::scoped_lock lock(g_timers_lock);
                    g_timers.insert(std::make_pair(count++, pt));
            }

            usleep(20000);
    }

    return 0;
}

==================================

我知道,我应该锁定g_timers,但是我应该锁定g_ios吗? 我的意思是这些:

ba::deadline_timer* pt = new ba::deadline_timer(g_ios, bp::seconds(1));
pt->async_wait(boost::bind(&on_timer, count));

线程安全吗?它引用了g_ios,它会调用g_ios.add_job(this_timer)..etc ..吗?

1 个答案:

答案 0 :(得分:2)

直接回答你的问题,是io_service的实例是线程安全的。这在documentation

中有所描述
  

线程安全

     

不同的对象:安全。

     

共享对象:安全,具有reset()和的特定例外情况   notify_fork()功能。在未完成时调用reset()   run()run_one()poll()poll_one()调用导致未定义   行为。任何时候都不应该调用notify_fork()函数   io_service函数,或I / O对象上的任何函数   与io_service相关联的,正在另一个线程中调用。

尽管如此,对我来说,你想要实现的目标并不明显。如上所述,您的示例没有任何结果,因为io_service在您调用io_service::run()时无需执行任务,因此会立即返回。您忽略了return value,我怀疑如果您检查它,它将为零。

您对互斥锁的使用也值得怀疑。通常,如果需要从异步处理程序中访问共享资源,则更喜欢使用strand而不是互斥锁。在Asio示例和documentation中很好地讨论了这个概念,threads的使用也是如此。