When should I prefer the first piece of code to the second, and do they have fundamental differences
std::mutex mtx; mtx.lock(); ... //protected stuff mtx.unlock(); ... //non-protected stuff mtx.lock(); ... //etc
and
std::mutex mtx; std::unique_lock<std::mutex> lck(mtx); ... //protected stuff lck.unlock(); ... //non-protected stuff lck.lock(); ... //etc
I do understand that lock_guard is basically a unique_lock without the lock and unlock functions, but I'm having hard time differentiating a mutex and a lock using a mutex.
The std::scoped_lock and std::unique_lock objects automate some aspects of locking, because they are capable of automatically unlocking.
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.
The benefit to using std::unique_lock<> comes from two things: 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.
Yes, the std::unique_lock
calls unlock on the mutex in its destructor.
The benefit of this is that in case some exception is thrown, you are sure that the mutex will unlock when leaving the scope where the std::unique_lock
is defined.
Think of it this way:
// define a mutex std::mutex mtx;
... much later ...
void something_safe() { // code in these braces is a critical section { auto lock = std::unique_lock<std::mutex>(mtx); // equivalent to mtx.lock(); ... //protected stuff } // <---- however you leave this brace, equivalent to mtx.unlock(); ... //non-protected stuff }
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