【问题标题】:Boost asio strand and io_service running on several threads提升在多个线程上运行的 asio strand 和 io_service
【发布时间】:2013-12-04 09:45:48
【问题描述】:

我不确定与股线相关的一个细节。

假设以下情况:两个独立的对象,每个对象都有自己的链。并且每条链都与一个常见的 io_service 相关。每个对象都使用他的链来发布和包装异步操作。如果我在多个线程上有这个(唯一的)io_service .run()'ing,我不确定是否会发生以下情况:

  1. 其中一个对象发布和异步包装的所有操作将非同时执行。因此,与其中一个对象相关的所有操作都将按顺序执行(发布的操作将按照与发布的顺序相同的顺序执行。包装的异步操作将按未指定的顺序执行,因为它们是异步的,但仍按顺序执行)。

  2. 源自不同对象的两个操作(因此从与同一 io_service 相关的不同 strand 对象发布或包装)可以同时执行

  3. 总而言之,每个对象将依次执行其发布和包装的处理程序,但从不同对象(链)发布和包装的处理程序将同时执行。

       +-----------------+  +-----------------+
       | Obj1            |  | Obj2            |
       | +-------------+ |  | +-------------+ |             
       | |   Strand_1  | |  | |   Strand_2  | |               
       | +-------------+ |  | +-------------+ |                
       +--------+--------+  +-------+---------+                
                |                   |                          
                +--------+  +-------+                          
                         |  |                                         
                    +----+--+----+                                      
                    | io_service |                                      
                    +------------+                                      
                           |                                          
                           |                                          
                  +--------+-------+                         
                  |                |                                
             Thread1             Thread_2  
             io_service.run()    io_service.run()                              
    

我说的对吗?

谢谢

【问题讨论】:

    标签: c++ multithreading asynchronous boost-asio


    【解决方案1】:

    简而言之,strand 保证其自己的处理程序的顺序调用,但不保证来自不同链的处理程序的并发执行。因此,这些问题的答案是:

    1. 是的。保证顺序调用。
    2. 是的。并发执行可能发生,但不能保证。
    3. 同意顺序调用,但不同意并发执行发生。

    strand 维护自己的处理程序队列,并保证其处理程序中只有一个处理程序位于 io_service 中,从而导致处理程序在放入 io_service 之前被同步。因此,所有通过strand 发布或调度的处理程序都将按顺序执行。

    可能会同时执行通过不同strands 发布或调度的处理程序,但不能保证会发生。 documentation 声明:

    实现不保证通过不同的链对象发布或分派的处理程序将被同时调用。

    因此,如果Thread1 正在执行通过Strand_1 发布的处理程序,Boost.Asio 将不会使用该信息来保证通过Strand_2 发布的处理程序将由@987654332 执行@;但是,有可能会根据其他实现细节选择Thread2 来执行Strand_2 中的处理程序,例如作为运行io_service 的线程列表中的下一个可用线程。

    例如,考虑 3 个处理程序 ABC 准备在 io_service 内运行的情况:

    • A 是通过 Strand_1 发布的。
    • B 不是通过 strand 发布的。
    • C 是通过 Strand_2 发布的。

    如果Thread1Thread2 正在运行io_service,那么一种可能的执行顺序是:

    Thread1         | Thread2
    ----------------+----------------
    start A()       | start B()
    `-- finish A()  | |
    start C()       | `-- finish B()
    `-- finish C()  |
    

    图示的执行顺序表明,通过不同的strands(分别为Strand_1Strand_2)发布的处理程序(AC)不能保证同时执行。

    【讨论】:

    • 谢谢。是否可以强制一些并发?我不太明白,如果 io_service 在多个线程中运行并且需要执行处理程序,为什么不使用“免费”线程之一。我的意思是,在多个线程中运行 io_service 是否毫无意义(假设我的问题中描述了一个方案)?
    • “不保证”,在通过不同的链对象发布或分派的并发调用处理程序的上下文中,意味着大多数时间都会发生这种情况,但并非总是如此?是否值得在多个线程中运行 io_service 以便在原始方案中获得一些性能?
    • @ChrisPeterson 我更新了答案,希望能更清楚地说明保证(或缺乏保证)提供的内容。如果有可用的线程,那么 Boost.Asio 将使用它来执行处理程序。如果需要同时调用多个处理程序,那么多个线程可能会有所帮助。
    • 非常好的文章 Tanner,+1。一个问题 - 如果我们有多个使用相同 io_service 的线程,并且所有完成处理程序都包装在同一个链中,这是否等同于我们只有一个线程的情况?如果我没记错的话,所有处理程序都应该按顺序调用,所以使用多个线程没有好处吗?
    • @MiljenMikic 我和你有同样的问题,我想是的。实际上,当我们只使用一个线程来运行所有处理程序时,处理程序是按顺序执行的,称为 implicit strand
    【解决方案2】:

    由其中一个对象发布和异步包装的所有操作将非并发执行。因此,与其中一个对象相关的所有操作都将按顺序执行(发布的操作将按照与发布的顺序相同的顺序执行。包装的异步操作将按未指定的顺序执行,因为它们是异步的,但仍按顺序执行)。

    是的。

    源自不同对象的两个操作(因此从与同一 io_service 相关的不同 strand 对象发布或包装)可以同时执行。

    是的

    总而言之,每个对象将依次执行其发布和包装的处理程序,但从不同对象(链)发布和包装的处理程序将同时执行。

    是的

    【讨论】:

      猜你喜欢
      • 2018-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-07
      • 2020-05-02
      • 2012-04-04
      • 1970-01-01
      相关资源
      最近更新 更多