Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is unlocking a lock_guard manually undefined/bad design?

Tags:

c++

c++11

mutex

I've got code thats something like this:

do {
    lock_guard<mutex> lck(globalMtx);
    auto itr = someMap.end();
    for (/*conditions*/){
        //do stuff with itr and someMap
        // if a certain condition is met, we exit function with a return
        // globalMtx needs to be unlocked at that time
    }
    if (itr == someMap.end()){
        // I need to unlock the globalMtx here
        globalMtx.unlock()
        // A command is sent to modify someMap before we try again
        this_thread::sleep_for( chrono::seconds( 5 ) );
    } else {
        break;
    }
} while (true);

As you can see in the if scope, I need to unlock the globalMtx so that I can modify "someMap" before going through it again. I've read in many threads/forums/whatever that manually locking a mutex using mutex.lock()/unlock() is a bad idea and typically never done anymore with c++11 or above.

So what can I do in this case to control the mutex as I need, while still preventing any case where leaving the scope keeps the mutex locked?

like image 992
user1324674 Avatar asked Dec 07 '17 21:12

user1324674


People also ask

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.

What is the benefit of using std :: unique_lock <> between instances?

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.

Why use lock guard?

The point of lock_guard is just to make locking and unlocking the mutex easier for you. For example, if you manually lock / unlock , but your function throws an exception somewhere in the middle, it will never reach the unlock statement.

Is Scoped_lock movable?

scoped_lock is for the simple case of wanting to lock some number of mutex objects in a deadlock-free way. Locking a single mutex is just a special case of locking multiple ones. The object is completely immobile, and it's very simple.


1 Answers

No, you should not call std::mutex::unlock() directly in this case, as std::lock_guard destructor would call std::mutex::unlock() again and that would lead to UB. You can use std::unique_lock instead, which is not lightweight as std::lock_guard but allows you to call unlock() on it:

std::unique_lock<mutex> lck(globalMtx);
...
lck.unlock(); // lck object is aware that globalMtx is released and would do nothing in it's dtor after this
like image 141
Slava Avatar answered Sep 30 '22 18:09

Slava