C++ STL队列的线程安全

C++ STL队列的线程安全,c++,multithreading,stl,C++,Multithreading,Stl,我使用队列在线程之间进行通信。我有一个读卡器和多个写卡器线程。我的问题是,我是否需要在每次为读卡器使用队列中的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();

我使用队列在线程之间进行通信。我有一个读卡器和多个写卡器线程。我的问题是,我是否需要在每次为读卡器使用队列中的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++
}
//读卡器线程
getLock();
从队列中获取元素数
释放锁();
int i=0;
而(i

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

任何没有明确声明其线程安全保证的类型都应该始终由互斥锁控制。也就是说,您的实现的stdlib可能允许这种情况的一些变化,但您无法知道std::queue的所有实现

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

您可能会发现编写自己的容器适配器更容易、更好或更具可移植性,从而保证所需的安全。我不知道有什么东西能在Boost中对队列做到这一点


我对C++0x的了解还不够,不知道它是否有现成的解决方案,但这可能是另一种选择。

这完全取决于实现。C++标准没有提到线程或线程安全性,所以这是否会工作取决于您的实现如何处理队列元素。 在您的例子中,读取器实际上正在弹出队列,这被认为是一个写操作。我怀疑在这种情况下,当多个线程同时向一个容器写入数据时,是否有任何常见的实现能够保证线程安全。至少VC++没有:

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

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


正如其他人已经提到的,标准容器并不是保证线程安全所必需的,所以您所要求的内容无法移植实现。通过使用2个队列和一个队列指针(指示写入程序当前正在使用的队列),可以缩短读卡器线程锁定写入程序的时间

每位作者将:

  • 获取锁
  • 将元素推入队列指针当前指向的队列
  • 释放锁
然后,读者可以执行以下操作:

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

int i = 0;
while( i < numOfElements){
    queue.front();
    queue.pop();
    i++
}
  • 获取锁
  • 切换队列指针,指向第二个队列
  • 释放锁
  • 处理来自第一个队列的元素

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


如果可以避免在线程之间共享状态或资源,那么并发运行线程就没有问题。然后线程就不必担心彼此了,因为它们是完全隔离的,彼此之间没有任何影响。

你的直觉是正确的:即使你不能指望STD队列是线程安全的,但队列在设计上应该是线程安全的


<> P>一个很好的解释,为什么在C++中由线程安全、无锁队列的标准实现由

C++ +0x给出,它使程序员能够编写无锁(线程安全)算法,并提供标准互斥体,但是它没有任何现成的东西。写入程序总是将队列指针当前指向的任何队列附加到该队列(在首次获取锁之后)。在这种情况下,锁将保护指针当前引用的队列(以及指针本身);另一个队列(“第一个队列”)可以由持有锁的读卡器进行处理。朴素的无锁队列实现仅对特殊情况下的单个生产者、单个消费者以及编译器生成的代码中的内存障碍和原子读/写的更多假设部分“线程安全”。然而,实现真正的无锁线程安全队列是可能的,但并不是那么简单。