Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What special purpose does unique_lock have over using a mutex?

I'm not quite sure why std::unique_lock<std::mutex> is useful over just using a normal lock. An example in the code I'm looking at is:

{//aquire lock

        std::unique_lock<std::mutex> lock(queue_mutex);

        //add task
        tasks.push_back(std::function<void()>(f));

}//release lock

why would this preferred over

queue_mutex.lock();

//add task
//...

queue_mutex.unlock();

do these snippets of code accomplish the same thing?

like image 214
Syntactic Fructose Avatar asked May 27 '14 15:05

Syntactic Fructose


People also ask

What is the benefit of using std :: unique_lock?

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.

What is unique_lock mutex?

(since C++11) 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 difference between unique_lock and Lock_guard?

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.

Does unique_lock automatically unlock?

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.


2 Answers

[Do] these snippets of code accomplish the same thing?

No.

The first one will release the lock at the end of the block, no matter what the block is. The second will not release the lock at the end if the critical section is exited with a break, continue, return, goto, exception, or any other kind of non-local jump that I'm forgetting about.

like image 168
R. Martinho Fernandes Avatar answered Oct 02 '22 13:10

R. Martinho Fernandes


The use of unique_lock offers resiliency in the face of changes and errors.

  • If you change the flow to add intermediate "jumps" (return for example)
  • If an exception is thrown
  • ...

in any case, the lock is automatically released.

On the other hand, if you attempt to do it manually, you may miss a case. And even if you don't right now, a later edit might.


Note: this is a usual idiom in C++, referred to as SBRM (Scoped Bound Resources Management) where you tie down a clean-up action to stack unwinding so you are assured that, unless crash/ungraceful exit, it is executed.

It also shows off RAII (Resources Acquisition is Initialization) since the very construction of unique_lock acquires the resource (here the mutex). Despite its name, this acronym is also colloquially used to refer to deterministic release at destruction time, which covers a broader scope than SBRM since it refers to all kind of deterministic releases, not only those based on stack unwinding.

like image 39
Matthieu M. Avatar answered Oct 02 '22 14:10

Matthieu M.