Reputation: 145
I know my question is quite similar to this Why does std::lock_guard release the lock after using std::adopt_lock?, but the behavior I see is not. Here is my code:
#include <mutex>
#include <iostream>
using namespace std;
std::mutex m;
void fun2();
void fun1() {
cout << "fun1" << endl;
std::unique_lock<std::mutex> guard(m);
cout << "lock mutex" << endl;
fun2();
if (guard.owns_lock()) {
cout << "still holds mutex" << endl;
}
else {
cout << "doesn't hold mutex" << endl;
}
}
void fun2() {
std::lock_guard<std::mutex> guard(m, std::adopt_lock);
cout << "fun2" << endl;
}
int main(int argc, char* argv[]) {
fun1();
return 0;
}
And this is the result I get:
fun1
lock mutex
fun2
still holds mutex
Clearly, the unique_lock
in fun1
still holds the mutex. So my question is "Does std::lock_guard
release the mutex after constructed with std::adopt_lock
option?". Hope you all can help me clarify this situation. Thank you.
Upvotes: 4
Views: 1004
Reputation: 118077
The program has undefined behavior.
You've created two guards that both think they own the mutex
and they will both unlock
it. That's UB.
Using m.lock()
in fun1
instead of using a guard would be one way to make it have defined behavior.
Upvotes: 1
Reputation: 14987
When you constructed a std::unique_lock
to manage the mutex, you should stick to it unless you first break the association of the std::unique_lock
with the mutex using std::unique_lock::release. In your sample, you touched the raw mutex when it's still managed by a std::unique_lock
and this is wrong.
Upvotes: 2