C++ What are the differences between std::lock and std::unique_lock? - c++

I came into a situation where I need to lock a resource (a std::queue) between two processing threads.
The first thread needs to push data to std::queue, while the second thread is going to pop that data out of the queue and process it.
I need to make sure both threads will not compete for my std::queue.
As this is my first time using C++ locks, I came into different approaches: std::lock and std::unique_lock, but I don´t know which one to choose...
What is the difference between std::lock and std::unique_lock and how they should be used.
Thanks for helping.

std::lock is an algorithm that locks a collection of lockable objects all at once in a specific way that avoids deadlocks.
std::unique_lock is a class template that wraps a mutex and can be used as a scoped lock guard, similar to std::lock_guard, but more powerful than the latter (it is itself lockable, can be unlocked early and can be moved around).
You probably want neither of those, but instead just use the good old std::lock_guard.

Related

std::scoped_lock and mutex ordering

I'm trying to determine if std::scoped_lock tries to establish an ordering or mutex id to acquire locks in a prescribed order. Is not clear to me that it does it from a somewhat brief looking at a browsable implementation I found googling around.
In case it is not doing that, What would be the closest to standard implementation of acquiring an ordered set of locks?
Typically the cleanest way to avoid deadlocks is to always acquire a group of locks in the same order (and yes, sure, always release them all before trying to acquire new locks again, but perhaps 2PL is a little beyond the scope of what std::scoped_lock should aim to do)
The order for std::lock isn't defined until run-time, and it is not fixed. It is discovered experimentally by the algorithm for each individual call to std::lock. The second call to std::lock could lock the mutexes in a different order than the first, even though both calls might use the same list of mutexes in the same order at the call site.
Here is a detailed performance analysis of several possible implementations of std::lock: http://howardhinnant.github.io/dining_philosophers.html
Using a fixed ordering of the mutexes is one of the algorithms that is performance-compared in the above link. It is not the best performing algorithm for the experiments conducted.
The libstdc++ implementation the OP points to is a high quality implementation of what the analysis labels "Smart & Polite"
scoped_lock's constructor is stated to call std::lock on its mutexes, so its behavior is governed by this function. And std::lock is specifically defined to avoid deadlocks on what it locks. The order it locks the mutexes in is undefined, but it won't result in a deadlock.

Do mutexes guarantee ordering of acquisition? Unlocking thread takes it again while others are still waiting

A coworker had an issue recently that boiled down to what we believe was the following sequence of events in a C++ application with two threads:
Thread A holds a mutex.
While thread A is holding the mutex, thread B attempts to lock it. Since it is held, thread B is suspended.
Thread A finishes the work that it was holding the mutex for, thus releasing the mutex.
Very shortly thereafter, thread A needs to touch a resource that is protected by the mutex, so it locks it again.
It appears that thread A is given the mutex again; thread B is still waiting, even though it "asked" for the lock first.
Does this sequence of events fit with the semantics of, say, C++11's std::mutex and/or pthreads? I can honestly say I've never thought about this aspect of mutexes before.
Are there any fairness guarantees to prevent starvation of other threads for too long, or any way to get such guarantees?
Known problem. C++ mutexes are thin layer on top of OS-provided mutexes, and OS-provided mutexes are often not fair. They do not care for FIFO.
The other side of the same coin is that threads are usually not pre-empted until they run out of their time slice. As a result, thread A in this scenario was likely to continue to be executed, and got the mutex right away because of that.
The guarantee of a std::mutex is enable exclusive access to shared resources. Its sole purpose is to eliminate the race condition when multiple threads attempt to access shared resources.
The implementer of a mutex may choose to favor the current thread acquiring a mutex (over another thread) for performance reasons. Allowing the current thread to acquire the mutex and make forward progress without requiring a context switch is often a preferred implementation choice supported by profiling/measurements.
Alternatively, the mutex could be constructed to prefer another (blocked) thread for acquisition (perhaps chosen according FIFO). This likely requires a thread context switch (on the same or other processor core) increasing latency/overhead. NOTE: FIFO mutexes can behave in surprising ways. E.g. Thread priorities must be considered in FIFO support - so acquisition won't be strictly FIFO unless all competing threads are the same priority.
Adding a FIFO requirement to a mutex's definition constrains implementers to provide suboptimal performance in nominal workloads. (see above)
Protecting a queue of callable objects (std::function) with a mutex would enable sequenced execution. Multiple threads can acquire the mutex, enqueue a callable object, and release the mutex. The callable objects can be executed by a single thread (or a pool of threads if synchrony is not required).
•Thread A finishes the work that it was holding the mutex for, thus
releasing the mutex.
•Very shortly thereafter, thread A needs to touch a resource that is
protected by the mutex, so it locks it again
In real world, when the program is running. there is no guarantee provided by any threading library or the OS. Here "shortly thereafter" may mean a lot to the OS and the hardware. If you say, 2 minutes, then thread B would definitely get it. If you say 200 ms or low, there is no promise of A or B getting it.
Number of cores, load on different processors/cores/threading units, contention, thread switching, kernel/user switches, pre-emption, priorities, deadlock detection schemes et. al. will make a lot of difference. Just by looking at green signal from far you cannot guarantee that you will get it green.
If you want that thread B must get the resource, you may use IPC mechanism to instruct the thread B to gain the resource.
You are inadvertently suggesting that threads should synchronise access to the synchronisation primitive. Mutexes are, as the name suggests, about Mutual Exclusion. They are not designed for control flow. If you want to signal a thread to run from another thread you need to use a synchronisation primitive designed for control flow i.e. a signal.
You can use a fair mutex to solve your task, i.e. a mutex that will guarantee the FIFO order of your operations. Unfortunately, C++ standard library doesn't have a fair mutex.
Thankfully, there are open-source implementations, for example yamc (a header-only library).
The logic here is very simple - the thread is not preempted based on mutexes, because that would require a cost incurred for each mutex operation, which is definitely not what you want. The cost of grabbing a mutex is high enough without forcing the scheduler to look for other threads to run.
If you want to fix this you can always yield the current thread. You can use std::this_thread::yield() - http://en.cppreference.com/w/cpp/thread/yield - and that might offer the chance to thread B to take over the mutex. But before you do that, allow me to tell you that this is a very fragile way of doing things, and offers no guarantee. You could, alternatively, investigate the issue deeper:
Why is it a problem that the B thread is not started when A releases the resource? Your code should not depend on such logic.
Consider using alternative thread synchronization objects like barriers (boost::barrier or http://linux.die.net/man/3/pthread_barrier_wait ) instead, if you really need this sort of logic.
Investigate if you really need to release the mutex from A at that point - I find the practice of locking and releasing fast a mutex for more than one time a code smell, it usually impacts terribly the performace. See if you can group extraction of data in immutable structures which you can play around with.
Ambitious, but try to work without mutexes - use instead lock-free structures and a more functional approach, including using a lot of immutable structures. I often found quite a performance gain from updating my code to not use mutexes (and still work correctly from the mt point of view)
How do you know this:
While thread A is holding the mutex, thread B attempts to lock it.
Since it is held, thread B is suspended.
How do you know thread B is suspended. How do you know that it is not just finished the line of code before trying to grab the lock, but not yet grabbed the lock:
Thread B:
x = 17; // is the thread here?
// or here? ('between' lines of code)
mtx.lock(); // or suspended in here?
// how can you tell?
You can't tell. At least not in theory.
Thus the order of acquiring the lock is, to the abstract machine (ie the language), not definable.

When to use C++11 mutex, lock, unique_lock, shared_lock, etc

What is the difference between shared_lock and shared_mutex.lock_shared() other than that the destructor of shared_lock unlocks the associated mutex?
Is a shared_mutex the only mutex class I can use with shared_lock?
Why would someone want to use lock_guard instead of unique_lock?
If I have many threads constantly locking for reading (shared_lock) a variable and I have a variable that tries to lock it for writing (unique_lock), will this writing thread have a priority over the other ones?
For #4, is there a possibility for a deadlock?
shared_mutex.lock_shared() is a function call that locks shared_mutex in a shared mode, while shared_lock is a "lock-class" that is used to lock and automatically unlock mutex at the end of the scope.
No, you can use shared_lock with any type that meets the SharedMutex requirements.
Always use lock_guard unless you need additional functionality of unique_lock. This way your intent is more clear.
This does not depend on shared_lock or unique_lock, but on what SharedMutex you are using. Exact beheavior is not specified by the standard. But here are some clues:
On Windows shared_lock will usually be implemented using SRWLOCK and tries to be fair e.g. will try to balance readers and writers. No one will have higher priority here.
On POSIX systems shared_mutex will most likely be implemented on top of pthread_rwlock_t and implementations usually give preference to readers because of its requirement to support recursive read locks.
Boost shared_mutex tries to be fair and gives no preference to either side.
With reader-preferring shared_mutex it is possible for your writer thread to never acquire the lock if there is always at least one reader holding it.

is std::queue thread safe with producer and multiple consumers

how can I make a queue thread safe? I need to push / pop / front / back and clear. is there something similar in boost?
I have one producer and one or more consumer.
std::queue is not thread safe if one or more threads are writing. And its interface is not conducive to a thread safe implementation, because it has separate methods such as pop(), size() and empty() which would have to be synchronized externally.
A common approach* is to implement a queue type with a simpler interface, and use locking mechanisms internally to provide synchronization.
* A search for "concurrent queue C++" should yield many results. I implemented a very simple toy one here, where the limitation was to use only standard C++. See also Anthony Williams' book C++ concurrency in action, as well as his blog.
You must protect access to std::queue. If you are using boost protect it using boost::mutex. Now if you have multiple readers and one writer thread look at boost::shared_lock (for readers) and boost::unique_lock(for writer).
However if you will encounter writer thread starvation look at boost::shared_mutex.
in boost 1.53 there is a lockfee queue http://www.boost.org/doc/libs/1_53_0/doc/html/boost/lockfree/queue.html, no mutex or smth like this.
You have to protect it, e.g. with a std::mutex, on every operation. Boost would be an alternative if you don't have C++11 yet.

Differences between Conditional variables, Mutexes and Locks

For example the c++0x interfaces
I am having a hard time figuring out when to use which of these things (cv, mutex and lock).
Can anyone please explain or point to a resource?
Thanks in advance.
On the page you refer to, "mutex" is the actual low-level synchronizing primitive. You can take a mutex and then release it, and only one thread can take it at any single time (hence it is a synchronizing primitive). A recursive mutex is one which can be taken by the same thread multiple times, and then it needs to be released as many times by the same thread before others can take it.
A "lock" here is just a C++ wrapper class that takes a mutex in its constructor and releases it at the destructor. It is useful for establishing synchronizing for C++ scopes.
A condition variable is a more advanced / high-level form of synchronizing primitive which combines a lock with a "signaling" mechanism. It is used when threads need to wait for a resource to become available. A thread can "wait" on a CV and then the resource producer can "signal" the variable, in which case the threads who wait for the CV get notified and can continue execution. A mutex is combined with CV to avoid the race condition where a thread starts to wait on a CV at the same time another thread wants to signal it; then it is not controllable whether the signal is delivered or gets lost.
I'm not too familiar w/ C++0x so take this answer w/ a grain of salt.
re: Mutex vs. locks: From the documentation you posted, it looks like a mutex is an object representing an OS mutex, whereas a lock is an object that holds a mutex to facilitate the RAII pattern.
Condition variables are a handy mechanism to associate a blocking/signaling mechanism (signal+wait) with a mutual exclusion mechanism, yet keep them decoupled in the OS so that you as system programmer can choose the association between condvar and mutex. (useful for dealing with multiple sets of concurrently-accessed objects) Rob Krten has some good explanations on condvars in one of the online chapters of his book on QNX.
As far as general references: This book (not out yet) looks interesting.
This question has been answered. I just add this that may help to decide WHEN to use these synchronization primitives.
Simply, the mutex is used to guarantee mutual access to a shared resource in the critical section of multiple threads. The luck is a general term but a binary mutex can be used as a lock. In modern C++ we use lock_guard and similar objects to utilize RAII to simplify and make safe the mutex usage. The conditional variable is another primitive that often combined with a mutex to make something know as a monitor.
I am having a hard time figuring out when to use which of these things
(cv, mutex and lock). Can anyone please explain or point to a
resource?
Use a mutex to guarantee mutual exclusive access to something. It's the default solution for a broad range of concurrency problems. Use lock_guard if you have a scope in C++ that you want to guard it with a mutex. The mutex is handled by the lock_guard. You just create a lock_guard in the scope and initialize it with a mutex and then C++ does the rest for you. The mutex is released when the scope is removed from the stack, for any reason including throwing an exception or returning from a function. It's the idea behind RAII and the lock_guard is another resource handler.
There are some concurrency issues that are not easily solvable by only using a mutex or a simple solution can lead to complexity or inefficiency. For example, the produced-consumer problem is one of them. If we want to implement a consumer thread reading items from a buffer shared with a producer, we should protect the buffer with a mutex but, without using a conditional variable we should lock the mutex, check the buffer and read an item if it's not empty, unlock it and wait for some time period, lock it again and go on. It's a waste of time if the buffer is often empty (busy waiting) and also there will be lots of locking and unlocking and sleeps.
The solution we need for the producer-consumer problem must be simpler and more efficient. A monitor (a mutex + a conditional variable) helps us here. We still need a mutex to guarantee mutual exclusive access but a conditional variable lets us sleep and wait for a certain condition. The condition here is the producer adding an item to the buffer. The producer thread notifies the consumer thread that there is and item in the buffer and the consumer wakes up and gets the item. Simply, the producer locks the mutex, puts something in the buffer, notifies the consumer. The consumer locks the mutex, sleeps while waiting for a condition, wake s up when there is something in the buffer and gets the item from the buffer. It's a simpler and more efficient solution.
The next time you face a concurrency problem think this way: If you need mutual exclusive access to something, use a mutex. Use lock_guard if you want to be safer and simpler. If the problem has a clue of waiting for a condition that must happen in another thread, you MIGHT need a conditional variable.
As a general rule of thumb, first, analyze your problem and try to find a famous concurrency problem similar to yours (for example, see classic problems of synchronization section in this page). Read about the solutions proposed for the well-known solution to peak the best one. You may need some customization.