如何在多个线程中安全地使用提升截止时间计时器?

Posted

技术标签:

【中文标题】如何在多个线程中安全地使用提升截止时间计时器?【英文标题】:How to safely use boost deadline timer in multiple threads? 【发布时间】:2014-03-05 02:00:13 【问题描述】:

我像这样使用 boost deadline_timer 代码:

boost::asio::io_service g_io;
#define DEL(x) delete x; x = NULL;

void thr1()

    for(;;)
    

         ...
        boost::asio::deadline_timer *t1 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t1->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t1));

         ...
    



void thr2()

    for(;;)
    
           ....


        boost::asio::deadline_timer *t2 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t2->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t2));

            ....
    



void thr3()

    for(;;)
    

         ....

        boost::asio::deadline_timer *t3 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t3->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t3));

         ....
    



void thr4()

    for(;;)
    
         ....

        boost::asio::deadline_timer *t4 = new boost::asio::deadline_timer(g_io, boost::posix_time::seconds(60));
        t4->async_wait(boost::bind(&callback, boost::asio::placeholders::error, t4));

        ....
    


void io_work()

    boost::asio::io_service::work work(g_io);
    g_io.run();



int main()

    boost::thread thread1(thr1);
    boost::thread thread2(thr2);
    boost::thread thread3(thr3);
    boost::thread thread4(thr4);

    boost::thread service_thread(io_work);

    thread1.join();
    thread2.join();
    thread3.join();
    thread4.join();

    service_thread.join();

    return 0;




void callback(const boost::system::error_code& e, boost::asio::deadline_timer *timer)

    if(e)
    
        std::cout << "cancel" << std::endl;
    
    else
    
        std::cout << " time out occurred" << std::endl;

        if(timer->expires_at() <= boost::asio::deadline_timer::traits_type::now())
          
            if(timer) DEL(timer);
            return;
        

        timer->expires_at(timer->expires_at()+boost::posix_time::seconds(1));
        timer->async_wait(boost::bind(callback, boost::asio::placeholders::error, timer));
    

计时器运行良好。但是,当出现奇怪的错误时,我总是首先怀疑我的 asio 代码,因为我找不到与我写的类似的 asio 代码。

没有任何互斥或同步,我可以在多线程中注册计时器吗?

另外,如果您在 mycode 中发现任何问题,请给我建议。

感谢您的阅读。

【问题讨论】:

callback你先删除timer,然后调用它的expires_atasync_wait成员函数。 谢谢。实际上我的真实代码有return语句。我修复了我的代码。 【参考方案1】:

截止时间计时器实例不是线程安全的。

单独的实例线程安全的。因此,要么使用单独的计时器,要么为访问添加同步。

文档链接:

http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/deadline_timer.html#boost_asio.reference.deadline_timer.thread_safety

【讨论】:

【参考方案2】:

您应该注意到,在调用io_service.run() 时,您的callback 函数将始终在线程中被调用,在您的情况下为service_thread。 因此,您在没有同步的情况下访问两个线程上的计时器对象,没有同步是不安全的。

但具体情况取决于您的完整代码(... 部分中的内容)。 如果您像在您的示例中那样完全这样做(仅在第一个线程中创建和启动计时器(保证在回调之前发生)并仅在 io_service 线程中访问它应该是安全的.

【讨论】:

以上是关于如何在多个线程中安全地使用提升截止时间计时器?的主要内容,如果未能解决你的问题,请参考以下文章

立即安全地终止线程 (C#)

如何避免计时器滴答中断主线程?

EJB 定时器服务线程安全吗?

While 循环计时如何在带有多个线程的 C# 中工作?

如何在 C# 的控制台应用程序中使用带有 Web 浏览器的计时器?

java线程怎么做个时间倒计时