I am confused regarding the reason why lock_guard
exists. Is it:
unique_lock
?unique_lock
?look up how a unique_lock() behaves. @Prab, just to give the explanation: unique_lock() is automatically released when the destructor is called meaning it is exception safe and that it automatically unlocks when you leave scope.
There are two primary benefits to using std::unique_lock<> over std::lock_guard<> : you can transfer ownership of the lock between instances, and. the std::unique_lock<> object does not have to own the lock on the mutex it is associated with.
A lock_guard always holds a lock from its construction to its destruction. A unique_lock can be created without immediately locking, can unlock at any point in its existence, and can transfer ownership of the lock from one instance to another.
The class unique_lock is a general-purpose mutex ownership wrapper allowing deferred locking, time-constrained attempts at locking, recursive locking, transfer of lock ownership, and use with condition variables.
lock_guard
can be implemented with one unit of state: a pointer or reference to the Mutex
type it has locked.
unique_lock
has to both hold that state, and knowing if it is currently locked, as a unique_lock
can have a Mutex
that is not locked. This means it must have at least a bool
of extra state.
lock_guard
provides a zero overhead RAII lock/unlock wrapper around acquiring and releasing a Mutex
. Basically the lock_guard
means that there is zero reason to avoid using RAII to handle locks on a Mutex
.
unique_lock
can only reach zero overhead if the compiler can be convinced to notice you only use it in ways that lock_guard
could be used (ie, construct it, then destroy it, without fiddling with it).
Beyond those efficiency arguments, a programmer who sees a lock_guard
knows that it is going to last until end of scope without having to examine the code in the scope. A programmer who sees a unique_lock
must examine all use of the variable to know if this is the case.
But the above is only half the reason.
The other half of the reason is because much of the threading library for C++11 was based off of boost
libraries, which had already implemented a mostly platform independent threading library. Boost has both lock_guard
and unique_lock
, with nearly identical semantics to the C++11 versions.
So when the boost
threading library was standardized, both where carried in, and nobody eliminated them.
You almost answer your own question here - 1) and 2) are both good reasons. std::lock_guard is a simple scoped locking object. Features like a timeout on mutex acquisition add to the complexity of the mutex primitive, increasing both the time it takes to perform the operation and the probability of contention for the mutex. So why pay for what you don't need?
Whether 'try_locking' with or without timeouts is good design is another question; like thread cancellation, a broken design which C++11 does not implement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With