多个线程使用相同的io_context以不同的时间间隔调用方法是否安全?

问题描述 投票:0回答:1

我有一个应用程序,我需要通过不同的线程在单个方法内调用多个方法。 每个方法应该以不同的时间间隔调用。 我正在使用 boost 库以不同的时间间隔重复执行调用函数。

我的问题是,对所有这些使用单个 boost::asio::io_context 是否安全?

这里是一个示例代码,展示了代码的外观。 枚举类型和类/结构声明将是

struct TestTimerContext {
    boost::asio::steady_timer timer;
    NssStatsTimerContext(boost::asio::io_context& io) : timer(io) {}
};


enum MethodTypes { FIRST = 0, SECOND = 1, THIRD = 2 };

class Myclass {
 
  public:
    Myclass(boost::asio::io_context& io): io_context_(io) {}
    void start_process (vector<bool> condistions, vector<uint32> intervals);

    std::thread                  method_1_thread_;
    std::thread                  method_2_thread_;
    std::thread                  method_3_thread_;
    
  private:
     boost::asio::io_context io_context_;
     
     void start_method_thread (uint32 interval, MethodTypes method_type);
 

     void func_cb ( const boost::system::error_code& err, uint32_t interval, MethodTypes method_type);

     void  method1 (uint32 interval);
     void  method1 (uint32 interval);
     void  method1 (uint32 interval);

};

这将是我如何使用 boost::asio::io_context 以不同的时间间隔调用该方法。我刚刚从示例代码中删除了所有逻辑,以分享高级想法并保持简单

Myclass::start_process (vector<bool> condistions, vector<uint32> intervals) {
    if (conditions[0]) {
        method_1_thread_ = std::thread([&]() {
            start_method_thread (intervals[0], MethodTypes::FIRST);
        });
    }
    if (conditions[1]) {
        method_2_thread_ = std::thread([&]() {
             start_method_thread (intervals[1], MethodTypes::SECOND);
        });
        
    }
    if (conditions[2]) {
       method_3_thread_ = std::thread([&]() {
            start_method_thread (intervals[2], MethodTypes::THIRD);
        });
    }
    if (method_1_thread_.joinable()) {
        method_1_thread_.join();
    }
    if (method_2_thread_.joinable()) {
        method_2_thread_.join();
    }
    if (method_3_thread_.joinable()) {
        method_3_thread_.join();
    }
}


void Myclass:: start_method_thread (uint32 interval, MethodTypes method_type) {
    std::unique_ptr<TestTimerContext> ctx;
    ctx           = std::make_unique<TestTimerContext>(io_context_);
    auto& ctx_ref = *ctx;
    
    if (interval ==0) {
        func_cb( err, interval, method_type);
    } else {
        
        ctx_ref.timer.expires_after(std::chrono::milliseconds(interval));
        ctx_ref.timer.async_wait([&](const boost::system::error_code& err) mutable {
            func_cb( err, interval, method_type);
        });
    }
}



void Myclass::func_cb (
    const boost::system::error_code& err,
    uint32_t                         interval,
    MethodTypes                         method_type) {

    if (err) {
        cout<<"cb function has an error"<<endl;
        return;
    }

    switch (method_type) {
    case MethodTypes::FIRST:
        method1();
        break;
    case MethodTypes::SECOND:
        methdo2();
        break;
    case MethodTypes::THIRD:
        method3();
        break;
    default:
        cout<<"method type is not supported"<<end;
        return;
    }

    if (interval == 0) {
        // do nothing
    } else {
        auto  ctx     = Arc<TestTimerContext>(io_context_);
        auto& ctx_ref = *ctx;

        ctx_ref.timer.expires_after(std::chrono::milliseconds(interval));
        ctx_ref.timer.async_wait([&](const boost::system::error_code& err) mutable {
            func_cb(err, interval, method_type);
        });
    }
}

void Myclass::method1 () {
    cout<<"method1 is called!"<<end;
    
}

void Myclass::method2 (){
    cout<<"method3 is called!"<<end;
}

void Myclass::method3 (){
    cout<<"method3 is called!"<<end;
}

如果您可以分享您的反馈,我将不胜感激,但是是的,我的主要问题是我是否可以在所有这些线程之间共享相同的 io_context 变量?

c++ multithreading boost
1个回答
0
投票

是的,对示例中的所有计时器和线程使用单个 boost::asio::io_context 是安全的。 io_context 旨在同时处理多个异步操作,因此您可以将它用于所有计时器和线程,而不会出现任何问题。

在您的代码中,每个计时器回调 (func_cb) 都与特定的 io_context 关联,这确保回调在创建它们时使用的 io_context 上下文中执行。这使您可以安全地为所有计时器和线程使用单个 io_context。

但是,请记住,您需要确保 io_context 的寿命比使用它的所有计时器和线程都长。这通常意味着您应该适当管理 io_context 的生命周期,确保在所有计时器和线程完成其操作之前它不会被销毁。

问题

您认为在不同线程上调用 async_wait 可以获得什么好处?需要明确的是,回调不会在调用 async_wait 的线程上调用;它将在调用 io_context_.run 的任何线程上调用。异步等待

回答

在不同线程上调用 async_wait 允许您安排多个异步操作同时执行。即使回调(在本例中为 func_cb)将在调用 io_context_.run() 的线程上调用,但使用多个线程调用 async_wait 可以帮助分配工作负载并提高应用程序的响应能力。

通过使用多个线程调用async_wait,可以确保不同的计时器同时处理,而不是等待一个计时器完成后再启动下一个计时器。如果您有多个具有不同间隔的计时器,并且您希望确保它们的处理时间尽可能接近其计划时间,则这尤其有用。

总的来说,使用多个线程调用 async_wait 可以让您同时处理多个异步操作,从而帮助提高应用程序的性能和效率。

© www.soinside.com 2019 - 2024. All rights reserved.