繁体   English   中英

STL队列的线程安全性

[英]Thread safety for STL queue

我正在使用队列来在线程之间进行通信。 我有一个读者和多个编写器线程。 我的问题是,每当我从队列中使用push / front / pop进行读取时,我是否需要锁定队列? 我可以做以下事情:

//reader threads
getLock();
get the number of elements from the queue
releaseLock();

int i = 0;
while( i < numOfElements){
    queue.front();
    queue.pop();
    i++
}

我的想法是,我想减少锁定代码的粒度,因为编写器线程只会写入队列的后面,并且只有一个读取器线程。 只要我获得了元素的数量,那么我就可以从队列中获取元素,或者我是否需要在锁中包含front()pop()

正如其他人已经提到的那样,标准容器不需要保证线程安全,因此您所要求的内容无法实现。 您可以通过使用2个队列和一个指示编写器当前正在使用的队列的队列指针来缩短读取器线程锁定写入器的时间。

每位作家都会:

  • 获取锁定
  • 将元素推入队列指针当前指向的队列中
  • 解锁

然后读者可以执行以下操作:

  • 获取锁定
  • 切换队列指针指向第二个队列
  • 解锁
  • 处理第一个队列中的元素

任何未明确声明其线程安全保证的类型应始终由互斥锁控制。 也就是说,你的实现的stdlib可能允许一些变化 - 但你不能知道std :: queue的所有实现。

当std :: queue包装另一个容器(它是容器适配器)时,您需要查看底层容器,默认为deque。

您可能会发现编写自己的容器适配器更容易,更好或更便携,从而提供所需的保证。 我不知道为Boost中的队列做了什么。

我没有看过C ++ 0x足以知道它是否有任何开箱即用的解决方案,但这可能是另一种选择。

这绝对是依赖于实现的。 C ++标准没有提及线程或线程安全性,因此这是否有效取决于您的实现如何处理队列元素。

在您的情况下,读者实际上弹出队列,这被认为是写操作。 我怀疑当多个线程同时写入容器时,任何常见的实现实际上都保证了线程安全性。 至少VC ++没有:

对于对同一对象的读取,当没有其他线程上的编写器时,该对象对于读取是线程安全的。

对于对同一对象的写入,当没有其他线程上的读取器时,该对象对于从一个线程写入是线程安全的。

你的预感是正确的:即使你不能指望STD队列是线程安全的,一个队列应该是线程安全的设计

van Dooren给出了一个很好的解释,为什么会这样,并且在C ++中使用线程安全,无锁队列的标准实现

有时,您可以通过避免在线程之间共享状态或资源来解决许多并发问题。 如果您有多个线程同时访问容器以便推进其工作,那么尝试让它们在专用容器上工作。 然后,在特定点,您将以非并发方式将容器的元素收集到中央容器中。

如果您可以避免在线程之间共享状态或资源,那么您可以同时运行线程没有问题。 然后线程不必互相担心,因为它们完全是孤立的,对彼此没有任何影响。

暂无
暂无

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

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