1

我打算做以下事情:

存储要使用的预构建对象的双端队列。主线程可能会到处使用这些对象。我有另一个垃圾线程用于日志记录和其他时间不紧迫但昂贵的事情。当预建对象用完时,我会在垃圾线程中重新填充它们。

现在我的问题是,这里会有比赛条件吗?从技术上讲,一个线程从前面消耗对象,另一个线程将对象推到后面。只要我不让尺寸下降到零,应该没问题。我唯一关心的是这个双端队列的“大小”。他们是否在 STL 容器中存储整数“大小”变量?修改该大小变量是否应该引入竞争条件?

解决这个问题的最佳方法是什么?我真的不想使用锁,因为主线程对性能至关重要(我首先预构建这些对象的原因!)

4

4 回答 4

8

STL 容器不是线程安全的,句号,不要玩这个。具体来说,双端队列元素通常存储在一个短数组链中,并且在使用双端队列操作时会修改该链,因此有很大的空间可以搞砸。

于 2012-06-01T13:35:39.043 回答
4

另一种选择是有 2 个双端队列,一个用于读取另一个用于写入。主线程读取,其他线程写入。当读取的双端队列为空时,切换双端队列(只需移动 2 个指针),这将涉及锁定,但只是偶尔。

消费者线程将驱动切换,因此它只需要在切换时进行锁定。生产者线程需要在每次写入时锁定,以防切换发生在写入过程中,但正如您提到的,消费者对性能的要求较低,所以不用担心。

正如其他人提到的那样,您关于无锁的建议确实很危险。

于 2012-06-01T13:36:12.507 回答
1

正如@sharptooth 提到的,STL 容器不是线程安全的。您使用的是支持 C++11 的编译器吗?如果是这样,您可以使用原子类型实现无锁队列。否则,您需要使用汇编程序进行比较和交换或使用特定于平台的 API(请参阅此处)。请参阅此问题以获取有关如何执行此操作的信息。

我要强调的是,您应该在使用标准线程同步时测量性能,看看您是否真的需要无锁技术。

于 2012-06-01T13:52:52.957 回答
0

即使是 non-empty 也会有数据竞争deque

您必须保护对直通锁的所有访问(不仅仅是写入)deque,或者使用专为多线程环境中的消费者-生产者模型设计的队列(例如 Microsoft 的unbounded_buffer)。

于 2012-06-01T13:38:25.033 回答