Use std::mutex for a thread pool managed by boost::asio

前端 未结 4 1379
执笔经年
执笔经年 2021-01-03 08:36

Somehow a followup of this question. I am only wondering if it is ok to use a std::mutex in functions handeled by a boost::asio:io_service? Usage o

相关标签:
4条回答
  • 2021-01-03 08:54

    Mutex inside completion handler can block thread execution. In that case you need more io_service threads than boost::thread::hardware_concurrency() to load CPU for 100%. It increases thread switching overhead.

    0 讨论(0)
  • 2021-01-03 09:05

    Yes, using a std::mutex inside of a handler is perfectly fine. A strand is just a queue with a mutex in disguise after all.

    0 讨论(0)
  • 2021-01-03 09:14

    boost is simply calling a callback from its perspective. This callback has no relation to boost, so boost doesn't care what you do in the callback. So taking a lock (using any locking library you desire), is perfectly fine.

    0 讨论(0)
  • 2021-01-03 09:16

    As others have noted, std::mutex and other locking mechanics, can be be used within handlers. However, there is a fundamental difference between the two:

    • An external locking mechanism within a handler is used to protect resources from race conditions.
    • A strand is used to remove contention between handlers, resulting in the removal of race conditions between handlers.

    If the entire handler is being synchronized as a result of potential race conditions with other handlers, and not threads external to the threadpool, then I would like to accentuate one of the subtle differences in synchronization between an external mechanism and boost::asio::strand.

    Consider the following scenario:

    • A threadpool of 2 threads is implemented with Boost.Asio.
    • Handlers A and B will be synchronized on the same mutex.
    • Handler C requires no synchronization.
    • Handlers A, B, and C are posted into the io_service.

    A and B are invoked. The threadpool is now exhausted due to external synchronization, as both threads are being used. Unfortunately, one of the threads is blocked on a resource, causing handlers that require no synchronization, such as C, to sit in the queue.

    If a strand is used for synchronization in this scenario, then this instance of starvation would not have occurred. A strand maintains its own handler queue, and guarantees that only one of its handlers is in the io_service, resulting in handlers being synchronized before being placed into the io_service. In the scenario, if A and B are posted into the strand, then the strand will post A into the io_service. This would result in A and C being in the io_service, allowing C to run concurrently while B remains in the strand's queue waiting for A to complete.

    Also, there are use cases where both of these forms of synchronization can be used together. For example, consider the case where resources are shared with a thread running outside of the threadpool. A mutex would still be required by threads internal and external to the threadpool. However, a strand could be used to remove the contention for the mutex between threads internal to the threadpool.

    0 讨论(0)
提交回复
热议问题