我有多个消费者线程和一个生产者线程。生产者线程将数据写入属于某个消费者线程的映射中,并向消费者线程发送信号。当我插入和删除数据时,我在地图周围使用互斥锁。但是这种方法在速度性能方面看起来效率不高。你能否建议另一种方法,而不是需要互斥锁和解锁的地图,我认为互斥会减慢传输速度。
答案 0 :(得分:2)
然而,这种方法在速度性能方面看起来效率不高。你能否建议另一种方法,而不是需要互斥锁和解锁的地图,我认为互斥会减慢传输速度。
您应该使用分析器来识别瓶颈所在。
生产者线程将数据写入属于某个消费者线程的映射中,并向使用者线程发送信号。
生产者不应该关心消费者使用什么样的数据结构 - 这是消费者的实施细节。请记住,在映射中插入值需要内存分配(除非您使用自定义分配器),内存分配内部也需要锁以保护堆的状态。最终结果是,在map::insert
操作周围锁定互斥锁可能会将其锁定太长时间。
更简单,更有效的设计是在生产者和消费者之间建立一个原子队列(例如pipe,TBB concurrent_bounded_queue预分配其存储,以便推/快操作非常快。由于您的生产者直接与每个消费者通信,该队列是一个写入者 - 一个读者,它可以实现为无等待队列(或环形缓冲区a-la C++ disruptor)。
答案 1 :(得分:0)
Andrei Alexandrescu提出了一个很好的观点,你应该测量你的代码(https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920),这与我给你的建议是一样的,即测量代码并查看你在代码之间获得的性能差异。基线测试和运行单线程的测试:
如果您仍在寻找一个线程安全的容器,您可能希望在{{3}处查看英特尔的线程安全容器的开源实现}。
此外,作为消费者线程实施的建议,您可能需要阅读其网站上发布的 Herb Sutter 的 ActiveObject 文章:http://www.threadingbuildingblocks.org/docs/help/reference/containers_overview/concurrent_queue_cls.htm < / p>
如果您可以提供更多详细信息,例如为什么地图必须一直被锁定,我们可能会起草一个效果更好的机制。