Search code examples
multithreadingc++11stdmutexcritical-section

Calling unlock on a mutex associated with a unique_lock causes undefined behavior


I wrote a simple code where I take a unique_lock and unlock the mutex instead of calling unlock on the lock itself. When the first thread enters the critical section and calls my_mutex.unlock(), many other threads enter the critical section together.

std::mutex my_mutex;
void sample() {
   std::unique_lock<std::mutex> lock(my_mutex);
   // Critical section
   my_mutex.unlock();
}

Why is this happening? Is it wrong to call unlock on a mutex held by a unique_lock? Thanks!


Solution

  • The UB is not caused by the explicit unlock using std::mutex::unlock, but by the second unlock that is performed by the std::unique_lock destructor when exiting the scope.

    From cppreference.com when calling std::mutex::unlock:

    The mutex must be locked by the current thread of execution, otherwise, the behavior is undefined.

    The solution is to not perform the explicit unlock on the mutex. Instead let the std::unique_lock unlock itself upon destruction as is intended.

    For cases where the lock needs to be released before destruction, use std::unique_lock::unlock which will allow for safe destruction. Alternatively you can simply insert an additional scope, e.g.:

    void sample() {
        // Before.
        {
            std::unique_lock<std::mutex> lock(my_mutex);
            // Critical section.
        }
        // After.
    }