当使用Visual Studio 2013进行编译时,以下程序会给出一些奇怪的编译/运行时行为:
#include "stdafx.h"
#include <thread>
#include <chrono>
#include <iostream>
int main()
{
{//works
std::thread([](){
std::cout << " thread running1n";
});
}
{//compile but synstax error exist
auto func = [](){
std::cout << " thread running2n";
};
std::thread(fun); //fun is not defined
}
{//compile, see next block for mystery compile error
auto func = [](){
std::cout << " thread running2n";
};
std::thread tmp(func);
}
{//does not compile and don't know why
auto func = [](){
std::cout << " thread running2n";
};
std::thread(func); //error C2371: 'func' : redefinition; different basic types
}
return 0;
}
当这个程序工作时,由于线程之间存在竞争条件,可能会崩溃。主线程可以先于其他线程结束。
有人知道为什么第二块和最后一块不起作用吗?
{//compile but synstax error exist
auto func = [](){
std::cout << " thread running2n";
};
std::thread(fun); //fun is not defined
}
这里没有语法错误,std::thread(fun)
默认构造一个名为fun
的std::thread
对象。
最后一个块中的错误是由于相同的原因
std::thread(func); //error C2371: 'func' : redefinition; different basic types
您试图在上面默认构造一个名为func
的std::thread
对象,这是一个错误,因为同一范围中已经存在同名的lambda。要将lambda传递给thread
构造函数,请使用大括号而不是
std::thread{func};
现在,在您进行了这些更改之后,您的代码将进行编译,但在运行时会失败,因为块1、3和4中的线程对象;4都将调用std::terminate
(当然,当第一个线程对象调用std::terminate
时,程序就会终止,所以其他两个这样做是没有意义的)。
发生这种情况的原因是,在所有3个块中都有可连接的线程,如果运行这样一个线程对象的析构函数,就会调用std::terminate
。为了避免这种情况,您必须拨打thread::join
(您也可以拨打thread::detach
,但不要这样做)。
例如
{//works
std::thread([](){
std::cout << " thread running1n";
}).join();
}
实时演示