直接看代码
#include<iostream>
#include <thread>
#include <ctime>
using namespace std;
struct func
{
int &m_i;
func(int &i) :m_i(i) {}
void operator()()
{
for (int i = 0; i < 10000000; ++i)
{
int addr = m_i++;
cout << addr << endl;
}
}
};
int main()
{
int main_a = 0;
func my_func(main_a);
thread my_thread(my_func);
my_thread.detach(); //线程剥离
std::this_thread::sleep_for(std::chrono::milliseconds(100);
return 0;
}
main函数的局部变量main_a被引用到函数对象my_func中,然后main 所在的主线程没有等待新线程返回就将新线程剥离,然后主线程休眠100ms结束,看一下多次运行结果:
显而易见,运行结果不可控了,因为局部变量main_a已经被释放,而子线程还在进行远操作,结果就是未知的了,而且是有害的,因为你修改的就是未知空间了。
可以将最后的my_thread.detach()改为my_thread.join()等待新线程返回然后原线程才继续。
#include<iostream>
#include <thread>
#include <ctime>
using namespace std;
struct func
{
int &m_i;
func(int &i):m_i(i){}
void operator()()
{
for (int i = 0; i < 100000; ++i) //为了节约时间,比起上面代码减少了100倍
{
int addr = m_i++;
cout << addr << endl;
}
}
};
int main()
{
int main_a = 0;
func my_func(main_a);
thread my_thread(my_func);
//my_thread.detach(); //线程剥离
my_thread.join();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 0;
}
运行结果如下:
从结果中可以看出,这次达到了我们想象中的效果,主线程等待新线程执行完毕。
但是调用join()的行为也会清理所有与该线程相关联的存储器,这样std::thread对象不再与现已完成的线程相关联,它也不与任何线程相关联。这就意味着,你只能对一个给定的线程调用一次join(),一旦你调用了join(),此std::thread对象不再是可连接的,并且joinbale()将返回false**
#include<iostream>
#include <thread>
#include <ctime>
using namespace std;
struct func
{
int &m_i;
func(int &i):m_i(i){}
void operator()()
{
for (int i = 0; i < 10; ++i)
{
int addr = m_i++;
cout << addr << endl;
}
}
};
int main()
{
int main_a = 0;
func my_func(main_a);
thread my_thread(my_func);
//my_thread.detach(); //线程剥离
cout<<"my_thread.joinable:"<<my_thread.joinable()<<endl;
my_thread.join();
cout<<"my_thread.joinable:"<<my_thread.joinable()<<endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 0;
}
运行结果:
人,总是要有一点精神的,不是吗?