Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::unique_lock<std::mutex> or std::lock_guard<std::mutex>?

I have two use cases.

A. I want to synchronise access to a queue for two threads.

B. I want to synchronise access to a queue for two threads and use a condition variable because one of the threads will wait on content to be stored into the queue by the other thread.

For use case A I see code example using std::lock_guard<>. For use case B I see code example using std::unique_lock<>.

What is the difference between the two and which one should I use in which use case?

like image 591
chmike Avatar asked Dec 11 '13 10:12

chmike


People also ask

What is the difference between std :: Lock_guard and std :: unique_lock?

The difference is that you can lock and unlock a std::unique_lock . std::lock_guard will be locked only once on construction and unlocked on destruction. So for use case B you definitely need a std::unique_lock for the condition variable.

What is the role of std :: mutex and std :: Lock_guard?

std::lock_guardA lock guard is an object that manages a mutex object by keeping it always locked. On construction, the mutex object is locked by the calling thread, and on destruction, the mutex is unlocked.

What is unique_lock mutex?

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.

What is the benefit of using std :: unique_lock?

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.


1 Answers

The difference is that you can lock and unlock a std::unique_lock. std::lock_guard will be locked only once on construction and unlocked on destruction.

So for use case B you definitely need a std::unique_lock for the condition variable. In case A it depends whether you need to relock the guard.

std::unique_lock has other features that allow it to e.g.: be constructed without locking the mutex immediately but to build the RAII wrapper (see here).

std::lock_guard also provides a convenient RAII wrapper, but cannot lock multiple mutexes safely. It can be used when you need a wrapper for a limited scope, e.g.: a member function:

class MyClass{     std::mutex my_mutex;     void member_foo() {         std::lock_guard<mutex_type> lock(this->my_mutex);                     /*          block of code which needs mutual exclusion (e.g. open the same           file in multiple threads).         */          //mutex is automatically released when lock goes out of scope     }            }; 

To clarify a question by chmike, by default std::lock_guard and std::unique_lock are the same. So in the above case, you could replace std::lock_guard with std::unique_lock. However, std::unique_lock might have a tad more overhead.

Note that these days (since, C++17) one should use std::scoped_lock instead of std::lock_guard.

like image 58
Stephan Dollberg Avatar answered Oct 04 '22 15:10

Stephan Dollberg