Я учусь о std::mutex
, std::thread
и я удивлен разным поведением двух частей кода ниже:
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
std::mutex mtx;
void foo(int k)
{
std::lock_guard<std::mutex> lg{ mtx };
for (int i = 0; i < 10; ++i)
cout << "This is a test!" << i << endl;
cout << "The test " << k << " has been finished." << endl;
}
int main()
{
std::thread t1(foo, 1);
std::thread t2(foo, 2);
t1.join();
t2.join();
return 0;
}
Выход является последовательным. Но если я не буду называть имя переменной std::lock_guard<std::mutex>
, выход неупорядоченный
void foo(int k)
{
std::lock_guard<std::mutex> { mtx }; // just erase the name of variable
for (int i = 0; i < 10; ++i)
cout << "This is a test!" << i << endl;
cout << "The test " << k << " has been finished." << endl;
}
Это похоже на std::lock_guard
бесполезно во втором случае, почему?
Эта декларация
std::lock_guard<std::mutex> { mtx };
не привязывает созданный объект к имени, это временная переменная, которая существует только для этого конкретного оператора. В противоположность этому переменная, которая имеет имя и создается в стеке, живет до конца области, в которой она создана.
В этот разговор CppCon (начинается с 31:42), ведущий перечисляет создание временных std::lock_guard
экземпляры, не связанные с локальной переменной, как распространенная ошибка в базе кода Facebook.
Других решений пока нет …