简体   繁体   English

使用std :: mutex作为boost :: asio管理的线程池

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

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 ? 我只是想知道在boost::asio:io_service函数中使用std::mutex可行? Usage of strands is somwhat unpractical. 使用股线是不切实际的。 From what I found in the boost reference I would say it is ok. 从我在boost参考中找到的我会说它没问题。 Since it states that 既然它说明了这一点

Asynchronous completion handlers will only be called from threads that are currently calling io_service::run(). 只能从当前调用io_service :: run()的线程调用异步完成处理程序。

So other threads created by boost should not interfere. 所以boost创建的其他线程不应该干扰。 Did I get it right? 我做对了吗?

As others have noted, std::mutex and other locking mechanics, can be be used within handlers. 正如其他人所说, std::mutex和其他锁定机制,可以在处理程序中使用。 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. 一条strand用于消除处理程序之间的争用,从而消除处理程序之间的竞争条件。

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 . 如果整个处理程序由于与其他处理程序的潜在竞争条件而被同步,而不是线程池外部的线程,那么我想强调外部机制和boost::asio::strand之间的同步中的一个细微差别。 boost::asio::strand

Consider the following scenario: 请考虑以下情形:

  • A threadpool of 2 threads is implemented with Boost.Asio. 使用Boost.Asio实现2个线程的线程池。
  • Handlers A and B will be synchronized on the same mutex. 处理程序AB将在同一个互斥锁上同步。
  • Handler C requires no synchronization. 处理程序C不需要同步。
  • Handlers A , B , and C are posted into the io_service . 处理程序ABC将发布到io_service

A and B are invoked. 调用AB 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. 不幸的是,其中一个线程在资源上被阻塞,导致不需要同步的处理程序(例如C位于队列中。

If a strand is used for synchronization in this scenario, then this instance of starvation would not have occurred. 如果在此方案中使用strand进行同步,则不会发生此饥饿实例。 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 . 一个strand维护自己的处理程序队列,并保证只有一个处理程序在io_service ,导致处理程序在被放入io_service之前被同步。 In the scenario, if A and B are posted into the strand , then the strand will post A into the io_service . 在该场景中,如果AB被发布到strand ,则strandA发布到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. 这将导致AC位于io_service ,允许C同时运行,而B保留在strand的队列中,等待A完成。

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. 但是,可以使用strand来消除线程池内部线程之间的互斥锁争用。

Yes, using a std::mutex inside of a handler is perfectly fine. 是的,在处理程序中使用std::mutex非常好。 A strand is just a queue with a mutex in disguise after all. 毕竟,一个strand只是一个伪装成互斥的队列。

boost is simply calling a callback from its perspective. boost只是从它的角度调用回调。 This callback has no relation to boost , so boost doesn't care what you do in the callback. 这个回调与boost无关,所以boost不关心你在回调中做了什么。 So taking a lock (using any locking library you desire), is perfectly fine. 因此,锁定(使用您想要的任何锁定库)是完全没问题的。

Mutex inside completion handler can block thread execution. Mutex内部完成处理程序可以阻止线程执行。 In that case you need more io_service threads than boost::thread::hardware_concurrency() to load CPU for 100%. 在这种情况下,您需要比boost::thread::hardware_concurrency()更多的io_service线程来加载100%的CPU。 It increases thread switching overhead. 它增加了线程切换开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM