Search code examples
c++multithreadingcrashlockingmutex

Passing std::unique_lock() with lock held to a thread as parameter in C++11


I am trying to pass a std::unique_lock() to a std::thread as shown in the below code snippet and the application crashes with "Unlock of unowned mutex" exception when I try to unlock() the lock in the thread in MSVS

std::mutex g_mutex; // Available globally

//SomeClass.cpp`
SomeClass::func1()
{
    std::unique_lock<std::mutex> lock(g_mutex);
    //Do stuff
    AnotherClass->func2(lock);`
}

//AnotherClass.cpp
AnotherClass::func2(std::unique_lock<std::mutex>& lock)
{
    //Do stuff
    //lock.unlock() works OK here
    thread = std::make_unique<std::thread>(std::bind(&AnotherClass:threadFun, this, std::ref(lock)));
    return;
}

AnotherClass::threadFunc(std::unique_lock<std::mutex>& lock)
{
    // Do stuff
    lock.unlock(); // Aborts the application with **"Unlock of unowned mutex"** here`
}

What's the issue here?

I tried passing passing the lock to the thread using std::move() and that didn't work either. I would like to know what mistake I am doing in the above code and is there better alternative to what I am doing?


Solution

  • The lock in func1 goes out of scope when the function returns. At that point, locks destructor is called and it will then call unlock() on the mutex.

    lock.unlock(); in threadFunc also unlocks the mutex and you therefore have a double unlock, with undefined behavior as a result.

    Also, you must only unlock the mutex from the thread which locked it:

    std::mutex::unlock:

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