boost::unique_lock vs boost::lock_guard - c++

I don't well understand the difference betweeen these two lock classes.
In boost documentation it is said, boost::unique_lock doesn't realize lock automatically.
Does it mean that the main difference between unique_lock and lock_guard is that with unique_lock we must call explicitly the lock() function ?

First to answer your question. No you don't need to call lock on a unique_lock. See below:
The unique_lock is only a lock class with more features. In most cases the lock_guard will do what you want and will be sufficient.
The unique_lock has more features to offer to you. E.g a timed wait if you need a timeout or if you want to defer your lock to a later point than the construction of the object. So it highly depends on what you want to do.
BTW: The following code snippets do the same thing.
boost::mutex mutex;
boost::lock_guard<boost::mutex> lock(mutex);
boost::mutex mutex;
boost::unique_lock<boost::mutex> lock(mutex);
The first one can be used to synchronize access to data, but if you want to use condition variables you need to go for the second one.

The currently best voted answer is good, but it did not clarify my doubt till I dug a bit deeper so decided to share with people who might be in the same boat.
Firstly both lock_guard and unique_lock follows the RAII pattern, in the simplest use case the lock is acquired during construction and unlocked during destruction automatically. If that is your use case then you don't need the extra flexibility of unique_lock and lock_guard will be more efficient.
The key difference between both is a unique_lock instance doesn't need to always own the mutex it is associated with while in lock_guard it owns the mutex. This means unique_lock would need to have an extra flag indicating whether it owns the lock and another extra method 'owns_lock()' to check that. Knowing this we can explain all extra benefits this flags brings with the overhead of that extra data to be set and checked
Lock doesn't have to taken right at the construction, you can pass the flag std::defer_lock during its construction to keep the mutex unlocked during construction.
We can unlock it before the function ends and don't have to necessarily wait for destructor to release it, which can be handy.
You can pass the ownership of the lock from a function, it is movable and not copyable.
It can be used with conditional variables since that requires mutex to be locked, condition checked and unlocked while waiting for a condition.

Their implementation can be found under path .../boost/thread/locks.hpp - and they are sitting just one next to other :) To sum things short:
lock_guard is a short simple utility class that locks mutex in constructor and unlocks in destructor, not caring about details.
unique_lock is a bit more complex one, adding pretty lot of features - but it still locks automatically in constructor. It is called unique_lock because it introduces "lock ownership" concept ( see owns_lock() method ).

If you're used to pthreads(3):
boost::mutex = pthread_mutex_*
boost::unique_lock = pthread_rwlock_* used to obtain write/exclusive locks (i.e. pthread_rwlock_wrlock)
boost::shared_lock = pthread_rwlock_* used to obtain read/shared locks (i.e. pthread_rwlock_rdlock)
Yes a boost::unique_lock and a boost::mutex function in similar ways, but a boost::mutex is generally a lighter weight mutex to acquire and release. That said, a shared_lock with the lock already acquired is faster (and allows for concurrency), but it's comparatively expensive to obtain a unique_lock.
You have to look under the covers to see the implementation details, but that's the gist of the intended differences.
Speaking of performance: here's a moderately useful comparison of latencies:
http://www.eecs.berkeley.edu/%7Ercs/research/interactive_latency.html
It would be nice if I/someone could benchmark the relative cost of the different pthread_* primitives, but last I looked, pthread_mutex_* was ~25us, whereas pthread_rwlock_* was ~20-100us depending on whether or not the read lock had been already acquired (~10us) or not (~20us) or writer (~100us). You'll have to benchmark to confirm current numbers and I'm sure it's very OS specific.

I think unique_lock may be also used when you need to emphasize the difference between unique and shared locks.

Related

How to lock multiple locks where some are shared and some are not in C++

Let's suppose I have some threadsafe class. It uses a std::shared_mutex for protection against concurrent access. Read only operations use a std::shared_lock, while write operations use std::scoped_lock.
Now, in the case of the copy assignment operator both the assignee's and the object's being assigned mutexes must be locked, except that the assignee gets modified and must have its mutex locked with std::shared_lock while the object being assign is read-only and must be locked using std::scoped_lock. As far as I know, locking multiple mutexes without using a specific lock ordering algorithm, like this, could cause a deadlock.
Normally a deadlock could be circumvented by using std::lock or std::scoped_lock, but in this case, they cannot be used, as one of the std::shared_mutexes must not be locked, but lock_shareded.
How can multiple locks be locked avoiding a deadlock, where some of them are shared and some are not?
In very same way you should be using function std::lock for multiple mutexes.
Let me give you an example:
std::mutex m;
std::shared_mutex sm;
std::unique_lock ul(m,std::defer_lock);
std::shared_lock sl(sm,std::defer_lock);
std::lock(ul,sl);
Function std::lock simply applies try_lock()/unlock() until it succedes on all input lockables whereas shared_lock's methods lock/try_lock impose shared locking (for reading).
Just fix your design so this doesn't happen. The issues with deadlock and difficulty of code maintenance are going to be intolerable with a design like this.
For example, maybe copy the source object to a temporary, unlock it, and then copy the temporary to the destination object. Or, alternatively, have a single lock that protects all the objects and architect so you don't hold it very long.

Difference between mutex.timed_lock(duration) and boost::timed_mutex::scoped_lock scoped_lock(mutex, duration)

I would like to know which is the difference between:
boost::timed_mutex _mutex;
if(_mutex.timed_lock(boost::get_system_time() + boost::posix_time::milliseconds(10))){
exclusive code
_mutex.unlock();
}
and
boost::timed_mutex _mutex;
boost::timed_mutex::scoped_lock scoped_lock(_mutex, boost::get_system_time() + boost::posix_time::milliseconds(10));
if(scoped_lock.owns_lock()) {
exclusive code
}
I do know already that the scoped_lock makes unnecessary the call to unlock. My question refers to:
Why in the first case we call timed_lock as member function of a
mutex and in the second one we construct a lock from a mutex and a
duration.
Which one is more efficient?
The usage of boost::posix_time is okay or is recommended to use another kind,
e.g. chrono or duration?
There's a better way (faster) to try to
acquire a lock for 'x' time than the two methods above specified?
I'll try to answer your questions:
as you can read in this Document, locks are used as RAII devices for the locked state of a mutex. That is, the locks don't own the mutexes they reference. They just own the lock on the mutex. basically what it means is that you acquire the mutex lock when you initialize it's corresponding lock and release it when the lock object is destroyed.
that's why in the second example you didn't have to call timed_lock from the mutex, the scoped_lock does it for you when initialized.
I don't know if the first example is more efficient but I know for sure that the second example (the RAII scoped_lock) is much safer, it guarantees that you won't forget to unlock the mutex and ,more important, it guarantees that other people that use and modify your code won't cause any mutex related problems.
as far as I know you can't construct scoped_lock (which is basicallyunique_lock<timed_mutex>) from posix_time. I personally prefer duration.
In my opinion constructing the lock with Duration absolute time is your best option.

Event notification without mutex

C++11 has the std::condition_variable, its wait function is
template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
It requires a mutex.
As far as I understand - its notify_one can be called without synchronization (I know the idiomatic way is to use it with a mutex).
I have an object which is already internally synchronized - so I don't need a mutex to protect it. One thread should wait for some event associated with that object, and others would be notified.
How to do such notification without a mutex in C++11? I.e. it is easy to do with a condition_variable, but it needs a mutex. I thought about using a fake mutex type, but std::mutex is nailed in the wait interface.
An option is to poll a std::atomic_flag + sleep, but I don't like sleeping.
Use std::condition_variable_any you can use any class with it which implements the BasicLockable Concept.
Given a bad feeling about this I checked the implementation of std::condition_variable_any of libc++. It turns out that it uses a plain std::condition_variable together with a std::shared_ptr to a std::mutex, so there is definitely some overhead involved without digging any deeper. (There is some other post here on SO which covers this, though I first have to search that)
As a matter of that I would probably recommend to redesign your case so that synchronization is really only done by a mutex protecting a plain condition variable.
In some threading models (although I doubt in modern ones) the mutex is needed to protect the condition variable itself (not the object you're synchronizing) from concurrent access. If the condition variable wasn't protected by a mutex you could encounter problems on the condition itself.
See Why do pthreads’ condition variable functions require a mutex?
I have some object, which already internally synchronized - I don't need mutex to protect it. One thread should wait for some event associated with that object, and others would notify.
If you don't hold the mutex the waiting thread is going to miss notifications, regardless whether you use condition_variable or condition_variable_any with the internal mutex.
You need to associate at least one bit of extra information with the condition variable, and this bit should be protected by a mutex.

C++11: why does std::condition_variable use std::unique_lock?

I am a bit confused about the role of std::unique_lock when working with std::condition_variable. As far as I understood the documentation, std::unique_lock is basically a bloated lock guard, with the possibility to swap the state between two locks.
I've so far used pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) for this purpose (I guess that's what the STL uses on posix). It takes a mutex, not a lock.
What's the difference here? Is the fact that std::condition_variable deals with std::unique_lock an optimization? If so, how exactly is it faster?
so there is no technical reason?
I upvoted cmeerw's answer because I believe he gave a technical reason. Let's walk through it. Let's pretend that the committee had decided to have condition_variable wait on a mutex. Here is code using that design:
void foo()
{
mut.lock();
// mut locked by this thread here
while (not_ready)
cv.wait(mut);
// mut locked by this thread here
mut.unlock();
}
This is exactly how one shouldn't use a condition_variable. In the regions marked with:
// mut locked by this thread here
there is an exception safety problem, and it is a serious one. If an exception is thrown in these areas (or by cv.wait itself), the locked state of the mutex is leaked unless a try/catch is also put in somewhere to catch the exception and unlock it. But that's just more code you're asking the programmer to write.
Let's say that the programmer knows how to write exception safe code, and knows to use unique_lock to achieve it. Now the code looks like this:
void foo()
{
unique_lock<mutex> lk(mut);
// mut locked by this thread here
while (not_ready)
cv.wait(*lk.mutex());
// mut locked by this thread here
}
This is much better, but it is still not a great situation. The condition_variable interface is making the programmer go out of his way to get things to work. There is a possible null pointer dereference if lk accidentally does not reference a mutex. And there is no way for condition_variable::wait to check that this thread does own the lock on mut.
Oh, just remembered, there is also the danger that the programmer may choose the wrong unique_lock member function to expose the mutex. *lk.release() would be disastrous here.
Now let's look at how the code is written with the actual condition_variable API that takes a unique_lock<mutex>:
void foo()
{
unique_lock<mutex> lk(mut);
// mut locked by this thread here
while (not_ready)
cv.wait(lk);
// mut locked by this thread here
}
This code is as simple as it can get.
It is exception safe.
The wait function can check lk.owns_lock() and throw an exception if it is false.
These are technical reasons that drove the API design of condition_variable.
Additionally, condition_variable::wait doesn't take a lock_guard<mutex> because lock_guard<mutex> is how you say: I own the lock on this mutex until lock_guard<mutex> destructs. But when you call condition_variable::wait, you implicitly release the lock on the mutex. So that action is inconsistent with the lock_guard use case / statement.
We needed unique_lock anyway so that one could return locks from functions, put them into containers, and lock/unlock mutexes in non-scoped patterns in an exception safe way, so unique_lock was the natural choice for condition_variable::wait.
Update
bamboon suggested in the comments below that I contrast condition_variable_any, so here goes:
Question: Why isn't condition_variable::wait templated so that I can pass any Lockable type to it?
Answer:
That is really cool functionality to have. For example this paper demonstrates code that waits on a shared_lock (rwlock) in shared mode on a condition variable (something unheard of in the posix world, but very useful nonetheless). However the functionality is more expensive.
So the committee introduced a new type with this functionality:
`condition_variable_any`
With this condition_variable adaptor one can wait on any lockable type. If it has members lock() and unlock(), you are good to go. A proper implementation of condition_variable_any requires a condition_variable data member and a shared_ptr<mutex> data member.
Because this new functionality is more expensive than your basic condition_variable::wait, and because condition_variable is such a low level tool, this very useful but more expensive functionality was put into a separate class so that you only pay for it if you use it.
It's essentially an API design decision to make the API as safe as possible by default (with the additional overhead being seen as negligible). By requiring to pass a unique_lock instead of a raw mutex users of the API are directed towards writing correct code (in the presence of exceptions).
In recent years the focus of the C++ language has shifted towards making it safe by default (but still allowing users to shoot themselves into their feet if they want to and try hard enough).

Need to mutex-protect (atomic) assignment sought by condition variable?

I understand how to use condition variables (crummy name for this construct, IMO, as the cv object neither is a variable nor indicates a condition). So I have a pair of threads, canonically set up with Boost.Thread as:
bool awake = false;
boost::mutex sync;
boost::condition_variable cv;
void thread1()
{
boost::unique_lock<boost::mutex> lock1(sync);
while (!awake)
cv.wait(lock1);
lock1.unlock(); // this line actually not canonical, but why not?
// proceed...
}
void thread2()
{
//...
boost::unique_lock<boost::mutex> lock2;
awake = true;
lock2.unlock();
cv.notify_all();
}
My question is: does thread2 really need to be protecting the assignment to awake? It seems to me the notify_all() call should be sufficient. If the data being manipulated and checked against were more than a simple "ok to proceed" flag, I see the value in the mutex, but here it seems like overkill.
A secondary question is that asked in the code fragment: Why doesn't the Boost documentation show the lock in thread1 being unlocked before the "process data" step?
EDIT: Maybe my question is really: Is there a cleaner construct than a CV to implement this kind of wait?
does thread2 really need to be protecting the assignment to awake?
Yes. Modifying an object from one thread and accessing it from another without synchronisation gives undefined behaviour. Even if it's just a bool.
For example, on some multiprocessor systems the write might only affect local memory; without an explicit synchronisation operation, other threads might never see the change.
Why doesn't the Boost documentation show the lock in thread1 being unlocked before the "process data" step?
If you unlocked the mutex before clearing the flag, then you might miss another signal.
Is there a cleaner construct than a CV to implement this kind of wait?
In Boost and the standard C++ library, no; a condition variable is flexible enough to handle arbitrary shared state and not particularly over-complicated for this simple case, so there's no particular need for anything simpler.
More generally, you could use a semaphore or a pipe to send a simple signal between threads.
Formally, you definitely need the lock in both threads: if any thread
modifies an object, and more than one thread accesses it, then all
accesses must be synchronized.
In practice, you'll probably get away with it without the lock; it's
almost certain that notify_all will issue the necessary fence or
membar instructions to ensure that the memory is properly synchronized.
But why take the risk?
As to the absense of the unlock, that's the whole point of the scoped
locking pattern: the unlock is in the destructor of the object, so
that the mutex will be unlocked even if an exception passes through.