Which STL container has a thread safe insertion process? I want several threads to simultaneously insert in the same container. Any implementation other than STL (i.e., Boost) is welcome!
The STL containers are not thread safe. You have to impose that yourself, should you so wish, with your own synchronisation.
I am trying to avoid the critical region in multi-threading because it deteriorates the performance !
On the contrary, it improves performance. Because the kind of locking a container class can do is only the very fine-grained kind, having to acquire the lock for each simple operation. That's expensive. When you take care of locking, you have the luxury of acquiring the lock and perform many operations. That does not improve the odds for concurrency but greatly reduces the locking overhead. You can choose the strategy that makes most sense for your app, it isn't forced on you.
Add to this that it is next to impossible to write a thread-safe container implementation that isn't either prone to deadlock or very expensive. Iterators are the problem. The library writer has to choose between taking a lock for the life time of the iterator (risking deadlock) or needs to update all live iterators when another thread changes the collection (expensive). Only the expensive choice is safe. Again, you choose the strategy that makes most sense, the expensive choice is not forced on you.
The Standard does not require any STL containers to be thread safe. An implementation could be thread safe, although I'm not sure how they could pull it off with the current API; and changing the API would make them no longer compatible with the Standard.
If the LGPL is acceptable, Intel TBB has thread safe containers (these containers use locks internally, which does affect their performance).
Take a look at Boost.Lockfree (http://www.boost.org/doc/libs/1_53_0/doc/html/lockfree.html). It provides threadsafe implementations of:
boost::lockfree::queue
a lock-free multi-produced/multi-consumer queue
boost::lockfree::stack
a lock-free multi-produced/multi-consumer stack
boost::lockfree::spsc_queue
a wait-free single-producer/single-consumer queue (commonly known as ringbuffer)
Containers follow KISS principle (Keep It Simple) and therefore do not have synchronization features. Most of the time this hypothetical embedded synchronization is not enough because most of the time access to some other objects must be synchronized with the access to the container. Combine your container with one lock, and that's it really.
Since you said any other (non-STL) implementation is welcome, I suggest Intel's Thread Building Blocks. They have thread safe concurrent containers that have really good performance characteristics.
Related
I am planning to do the following:
store a deque of pre-built objects to be consumed. The main thread might consume these objects here and there. I have another junky thread used for logging and other not time-critical but expensive things. When the pre-built objects are running low, I will refill them in the junky thread.
Now my question is, is there going to be race condition here? Technically one thread is consuming objects from the front, and another thread is pushing objects into the back. As long as I don't let the size run down to zero, it should be fine. The only thing that concerns me is the "size" of this deque. Do they store a integer "size" variable in STL containers? should modifying that size variable introduce race conditions?
What's the best way of solving this problem? I don't really want to use locks, because the main thread is performance critical (the reason I pre-built these objects in the first place!)
STL containers are not thread safe, period, don't play with this. Specifically the deque elements are usually stored in a chain of short arrays and that chain will be modified when operating with the deque, so there's a lot of room for messing things up.
Another option would be to have 2 deques, one for read another for write. The main thread reads, and the other writes. When the read deque is empty, switch the deques (just move 2 pointers), which would involve a lock, but only occasionally.
The consumer thread would drive the switch so it would only need to do a lock when switching. The producer thread would need to lock per write in case the switch happens in the middle of a write, but as you mention the consumer is less performance-critical, so no worries there.
What you're suggesting regarding no locks is indeed dangerous as others mention.
As #sharptooth mentioned, STL containers aren't thread-safe. Are you using a C++11 capable compiler? If so, you could implement a lock-free queue using atomic types. Otherwise you'd need to use assembler for compare-and-swap or use a platform specific API (see here). See this question to get information on how to do this.
I would emphasise that you should measure performance when using standard thread synchronisation and see if you do actually need a lock-free technique.
There will be a data race even with non-empty deque.
You'll have to protect all accesses (not just writes) to the deque through locks, or use a queue specifically designed for consumer-producer model in multi-threaded environment (such as Microsoft's unbounded_buffer).
I am looking for the optimal strategy to use STL containers (like std::map and std::vector) and pthreads.
What is the canonical way to go? A simple example:
std::map<string, vector<string>> myMap;
How do we guarantee concurrency?
mutex_lock;
write at myMap;
mutex_unlock;
Additionally, I would like to know if pthreads and STL face performance issues when used together.
System: Liunx, g++, pthreads, no boost, no Intel TBB
The C++03 Standard does not talk about concurrency at all, So the concurrency aspect is left out as an implementation detail for compilers. So the documentation that comes with your compiler is where one should look to for answers related to concurrency.
Most of the STL implementations are not thread safe as such.
Since STL containers do not provide any explicit Thread safety, So yes you will have to use your own synchronization mechanism. And while you are at it You should use RAII rather than manage the synchronization resource(mutex unlock etc) manually.
You can refer the Documentations here:
MSDN:
If a single object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected. For example, given an object A, if thread 1 is writing to A, then thread 2 must be prevented from reading from or writing to A.
GCC Documentation says:
We currently use the SGI STL definition of thread safety, which states:
The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe. If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.
Point to Note: GCC's Standard Library is a derivative of SGI's STL code.
The canonical way to provide concurrency is to hold a lock while accessing the collection.
That works in 90% of the cases where access to the collection isn't performance-critical anyway. If you're accessing a shared collection so much that locking around it harms performance, you should rethink your design. (And odds are, your design is okay and it won't affect performance anywhere near as much as you might suspect.)
You should take a look at intel thread building blocks tbb ( http://threadingbuildingblocks.org/ ). They have a few very optimized data structures that handle concurrency internally using non-blocking strategies.
I need several STL containers, threadsafe.
Basically I was thinking I just need 2 methods added to each of the STL container objects,
.lock()
.unlock()
I could also break it into
.lockForReading()
.unlockForReading()
.lockForWriting()
.unlockForWriting()
The way that would work is any number of locks for parallel reading are acceptable, but if there's a lock for writing then reading AND writing are blocked.
An attempt to lock for writing waits until the lockForReading semaphore drops to 0.
Is there a standard way to do this?
Is how I'm planning on doing this wrong or shortsighted?
This is really kind of bad. External code will not recognize or understand your threading semantics, and the ease of availability of aliases to objects in the containers makes them poor thread-safe interfaces.
Thread-safety occurs at design time. You can't solve thread safety by throwing locks at the problem. You solve thread safety by not having two threads writing to the same data at the same time- in the general case, of course. However, it is not the responsibility of a specific object to handle thread safety, except direct threading synchronization primitives.
You can have concurrent containers, designed to allow concurrent use. However, their interfaces are vastly different to what's offered by the Standard containers. Less aliases to objects in the container, for example, and each individual operation is encapsulated.
The standard way to do this is acquire the lock in a constructor, and release it in the destructor. This is more commonly know as Resource Acquisition Is Initialization, or RAII. I strongly suggest you use this methodology rather than
.lock()
.unlock()
Which is not exception safe. You can easily forget to unlock the mutex prior to throwing, resulting in a deadlock the next time a lock is attempted.
There are several synchronization types in the Boost.Thread library that will be useful to you, notably boost::mutex::scoped_lock. Rather than add lock() and unlock() methods to whatever container you wish to access from multiple threads, I suggest you use a boost:mutex or equivalent and instantiate a boost::mutex::scoped_lock whenever accessing the container.
Is there a standard way to do this?
No, and there's a reason for that.
Is how I'm planning on doing this
wrong or shortsighted?
It's not necessarily wrong to want to synchronize access to a single container object, but the interface of the container class is very often the wrong place to put the synchronization (like DeadMG says: object aliases, etc.).
Personally I think both TBB and stuff like concurrent_vector may either be overkill or still the wrong tools for a "simple" synchronization problem.
I find that ofttimes just adding a (private) Lock object (to the class holding the container) and wrapping up the 2 or 3 access patterns to the one container object will suffice and will be much easier to grasp and maintain for others down the road.
Sam: You don't want a .lock() method because something could go awry that prevents calling the .unlock() method at the end of the block, but if .unlock() is called as a consequence of object destruction of a stack allocated variable then any kind of early return from the function that calls .lock() will be guaranteed to free the lock.
DeadMG:
Intel's Threading Building Blocks (open source) may be what you're looking for.
There's also Microsoft's concurrent_vector and concurrent_queue, which already comes with Visual Studio 2010.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Is the C++ STL std::set thread-safe?
Thread safety for STL queue
I'm guessing it isn't, I just want to make sure.
meaning 2 threads using the same std::deque using std::deque::push_back or push_front at the same time.
Same question goes for std::priority_queue and the functions std::priority_queue::push and std::priority_queue::pop..
Are those containers thread-safe? Or I should personally program it to be thread-safe?
Tnx a lot.
From Scott Myer's Effective STL Item 12. Have realistic expectations about the thread safety of STL containers
Multiple readers are safe. Multiple threads may simultaneously read the contents of a single container, and this will work correctly. Naturally, there must not be any writers acting on the container during the reads.
Multiple writers to different containers are safe. Multiple threads may simultaneously write to different containers.
When it comes to thread safely and STL containers, you can hope for a library implementation that allows multiple readers
on one container and multiple writers on separate containers. You can't hope for the library to eliminate the need for manual concurrency control, and you can't rely on any thread support at all.
The STL does not provide any guarantees for thread safety. This is especially the case when modifying the same container from multiple threads.
The implementation of the STL that you're using may provide some level of thread safety, but you would need to look at the documentation for your implementation.
When you say are they thread safe, presumably you mean can you use them in multiple threads without having to lock anything.
In theory you could potentially have 2 threads, one pushing to the back and one to the front, and you'd probably get away with it although I would be wary because the implementor is not under a guarantee to make it thread safe as iterators become invalidated with inserts at either end, if the implementation of push_back used "end" and of push_front used "begin", such would be invalidated in the call by the other thread, and might blow up on you.
std::priority_queue is almost certainly not usable in two threads together, presumably for producer/consumer threads, with one pushing and one popping and you will need to lock first.
I found that when I wrote a producer/consumer queue based around std::deque, I allowed the producer also to push more than one item at a time, and the consumer to sweep the entire queue to process. This meant only one lock per bulk-insert, so reduced the number of times you needed to lock.
I have two questions about STL
1) why STL is not thread-safe? Is there any structure that is thread-safe?
2) How to debug STL using GDB? In GDB, how can I print a vector?
Container data structures almost always require synchronization (e.g. a mutex) to prevent race conditions. Since threading is not support by the C++ standard (pre C++0x), these could not be added to the STL. Also, synchronization is very expensive for cases where it is not needed. STL containers may be used in multi-threaded applications as long as you perform this synchronization manually. Alternatively, you may create your own thread-safe containers that are compatible with STL algorithms like this thread-safe circular queue.
A vector contains a contiguous block of memory. So, it can be displayed in the same way as a regular array once you find the pointer to this memory block. The exact details depend on the STL implementation you use.
The standard c++ containers are not thread safe because you most likely actually want higher level locking than just the containers themselves. In other words you are likely to want two or more operations to be safe together.
For example, if you have multiple threads running:
v.push_back(0);
v.push_back(1);
You wont get a nice vector of alternating 0's and 1's, they could be jumbled. You would need to lock around both commands to get what you want.
STL is not thread-safe because a lot of people don't need thread safety, and because that introduces threading context into classes that otherwise have no need to know anything about the concept of threads.
You can encapsulate access to containers and provide your own thread safety (or other restrictions imposed by your specific design and implementation.)
Because there are still single-threaded programs.
Take a look here.