开发者

Thread safety for STL queue

开发者 https://www.devze.com 2023-01-21 08:18 出处:网络
I am using a queue to communicate between threads. I have one reader and multiple writer threads. My question is do I need to lock the queue every time when I use push/front/pop from the 开发者_如何学

I am using a queue to communicate between threads. I have one reader and multiple writer threads. My question is do I need to lock the queue every time when I use push/front/pop from the 开发者_如何学Pythonqueue for the reader? Can I do something like the following:

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

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

The idea is that I want to reduce the granularity of the locked code and since the writer thread would only write to the back of the queue and there is only a single reader thread. As long as I get the number of elements, then I could get the elements from the queue OR do I need to enclose the front() and pop() in the lock as well?


As others have already mentioned, standard containers are not required to guarantee thread safety so what you're asking for cannot be implemented portably. You can reduce the time your reader thread is locking the writers out by using 2 queues and a queue pointer that indicates the queue that is currently in use by the writers.

Each writer would:

  • Acquire lock
  • Push element(s) into the queue currently pointed to by the queue pointer
  • Release lock

The reader can then do the following:

  • Acquire lock
  • Switch queue pointer to point to the second queue
  • Release lock
  • Process elements from the first queue


Any type that doesn't explicitly state its thread-safety guarantees should always be controlled by a mutex. That said, your implementation's stdlib may allow some variation of this — but you can't know for all implementations of std::queue.

As std::queue wraps another container (it's a container adapter), you need to look at the underlying container, which defaults to deque.

You may find it easier, better, or more portable to write your own container adapter that makes the guarantees you need. I don't know of anything that does this exactly for a queue in Boost.

I haven't looked at C++0x enough to know if it has any solution for this out-of-the-box, but that could be another option.


This is absolutely implementation-dependent. The C++ standard makes no mention about threads or thread safety, so whether or not this will work depends on how your implementation handles queue elements.

In your case, the reader is actually popping the queue, which is considered a write operation. I doubt any of the common implementations actually guarantee thread-safety in this case, when multiple threads simultaneously write to a container. At least VC++ does not:

For reads to the same object, the object is thread safe for reading when no writers on other threads.

For writes to the same object, the object is thread safe for writing from one thread when no readers on other threads.


Sometimes you can resolve a lot of concurrency headache by avoiding sharing state or resources among threads. If you have multiple threads that access a container concurrently in order to push in their work then try to have them work on dedicated containers. At specific points you then collect the containers' elements onto the central container in a non-concurrent manner.

If you can avoid sharing state or resources among threads then you have no problem running threads concurrently. Threads then need not worry about each other, because they are completely isolated and bear no effect whatsoever on each other.


Your hunch is correct: Even though you cannot count on STD queue to be thread safe, a queue should be thread safe by design.

A nice explanation of why that is the case and a standard implementation of thread safe, lock free queues in C++ is given by van Dooren

0

精彩评论

暂无评论...
验证码 换一张
取 消