我正在学习
std::mutex
,std::thread
,我对下面两段代码的不同行为感到惊讶:
#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;
}
输出是顺序的。但如果我不命名变量
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)
std::cout << "This is a test!" << i << std::endl;
std::cout << "The test " << k << " has been finished." << std::endl;
}
看起来
std::lock_guard
在第二种情况下没有用,为什么?
本声明
std::lock_guard<std::mutex> { mtx };
不会将创建的对象绑定到名称,它是一个临时变量,仅针对此特定语句而存在。与此相反,具有名称并在堆栈上创建的变量将一直存在,直到创建它的作用域结束为止。
在本次 CppCon 演讲(从 31:42 开始)中,演示者列出了创建未绑定到局部变量的临时
std::lock_guard
实例作为 Facebook 代码库中的常见错误。