c++mutexlock-guard

what is the scope of a c++ mutex lock guard?


I'm trying to figure out the scope of mutexes and mutex lock_guard and no one has been able to explain it to me. Consider the following c++ code:

void somefunction
{
    std::lock_guard<std::mutex> guard(mutex1);
    variable1++;

    std::lock_guard<std::mutex> guard(mutex2);  //what if I took this mutex out?
    variable2++;

    /*
    long block of code
    */

    variable3++;
}

I'm trying to determine what the rule for what a mutex lock_guard protects. For example, in the current code does mutex2 protect variable3? What if we took out mutex2? Does mutex1 then protect variable1 variable2 and variable3? How do I know what the mutex protects? Thank you


Solution

  • The std::lock_guard does not guard the variables. The std::lock_guard guards the mutex by ensuring that lock() and unlock() are called exactly once.
    It behaves like

    void somefunction
    {
        mutex1.lock();
        variable1++;
    
        mutex2.lock();  //what if I took this mutex out?
        variable2++;
    
        /*
        long block of code
        */
    
        variable3++;
        // I assume the long code block has no local variables whose destructors would modify the protected variables,
        // the destructors of local variables happen after the manual method calls.
        mutex2.unlock();  //what if I took this mutex out?
        mutex1.unlock();
    }
    

    The mutexes are responsible to guard (synchronize) the access to a shared resource (variables or a critical section or something else).
    It is a general problem that it may not be obvious which data is protected by which mutex as the mutex and variables are not directly bound to each other. It depends on the use case, but in some cases std::atomic can be a better solution, here it is obvious which variables are protected by what (the atomic variables protect themselves).

    Note: In this context I would assume that mutex1 belongs to variable1 and mutex2 belongs to variable2, variable3 is unclear

    As for //what if I took this mutex out?
    If something else accesses variable2 or variable3 while holding mutex2 but not mutex1, then there can be a data race.
    If every other access to variable2 and variable3 also has mutex1 locked, then mutex2 would indeed be useless and can be removed.