I'm learning about std::mutex
, std::thread
and I am surprised at the different behavior of 2 pieces of code below:
#include <iostream>
#include <mutex>
#include <thread>
std::mutex mtx;
void foo(int k)
{
std::lock_guard<std::mutex> lg{ mtx };
for (int i = 0; i < 10; ++i)
std::cout << "This is a test!" << i << std::endl;
std::cout << "The test " << k << " has been finished." << std::endl;
}
int main()
{
std::thread t1(foo, 1);
std::thread t2(foo, 2);
t1.join();
t2.join();
return 0;
}
The output is sequential. But if I donot name variable std::lock_guard<std::mutex>
, the output is unordered
void foo(int k)
{
std::lock_guard<std::mutex> { mtx }; // just erase the name of variable
for (int i = 0; i < 10; ++i)
std::cout << "This is a test!" << i << std::endl;
std::cout << "The test " << k << " has been finished." << std::endl;
}
It seems like std::lock_guard
is no use in 2nd case, Why?
This declaration
std::lock_guard<std::mutex> { mtx };
doesn't bind the created object to a name, it's a temporary variable that exists only for this particular statement. Opposed to that, a variable that has a name and is created on the stack lives until the end of the scope in which it's created.
In this CppCon talk (starting at 31:42), the presenter lists the creation of temporary std::lock_guard
instances not bound to a local variable as a common bug in the Facebook code base.