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!
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.
}