
包含头文件#include
void threadBegin()
{
}
thread a(threadBegin);//创建一个线程对象 括号里面需要放一个可调用对象用来构造对象 这个函数就变成这个线程的执行起点
void mprint(const int &a,char* b)
{
cout << a << endl;
cout << b << endl;
}
int main()
{
int a = 0;
char b[] = "abcd";
thread mobj(mprint,a,b);//这种方式将参数传入
//mobj.detach();
mobj.join();
return 0;
}
虽然用的是const int &a也就是引用方式 实际上子线程内部的a和主线程中的a地址不一样 并不是真的引用了 实际上是值传递
但是如果通过指针传递 子线程中的b和主线程的b是一个地址 所以这样是很危险的
因为直接传指针是不安全的 所以我们把这个指针存储的值转换成string会好点 就会变成值传递 但是还是会出现问题 因为并发的原因我们并不知道
char b[]是什么时候转换成string的 可能出现char b[]已经在主函数中被回收了 再进行string的类型转换 (这里没懂 如果会出现这个问题 那为什么int a可以实现传值 难道不会出现int a在主函数中被收回了 再值传递给子线程的a吗)
void mprint(const int &a,const string& b)
{
cout << a << endl;
cout << b << endl;
}
int main()
{
int a = 0;
char b[] = "abcd";
thread mobj(mprint,a,b);//正确方式是thread mobj(mprint,a,string(b)); 生成一个临时的string
//mobj.detach();
mobj.join();
return 0;
}
用类对象创建线程
当用类对象创建线程的时候 会复制一个类的对象到线程中去
所以如果主线程中的类对象销毁了 子线程中的类对象并不会被销毁
class A
{
public:
A()
{
cout << "A的构造函数"<<endl;
}
A(const A& a)
{
cout << "A的拷贝构造函数" << endl;
}
void operator()()
{
cout << "我是类";
}
~A()
{
cout << "A的析构函数" << endl;
}
};
int main()
{
A a;
thread mobj(a);
//mobj.detach();
mobj.join();
return 0;
}
会发现调用A的拷贝构造函数 说明是拷贝了一个A类对象到子线程中去
lambda表达式创建auto mylambda = []{
cout<<"lambda执行开始"<<endl;
cout<<"lambda执行结束"<<endl;
};
thread mobj(mylambda);
join()
阻塞主线程 让主线程等待子线程执行完毕 然后子线程和主线程汇合
detach()将子线程和主线程分离
void mprint()
{
cout << "第一个线程"<<endl;
cout << "第一个线程" << endl;
cout << "第一个线程" << endl;
cout << "第一个线程" << endl;
}
int main()
{
thread mobj(mprint);
mobj.detach();
cout << "main"<<endl;
cout << "main" << endl;
cout << "main" << endl;
cout << "main" << endl;
}
detach()后子线程和主线程失去联系 子线程驻留在后台运行 子线程由C++运行时库接管 子线程执行完成后由运行时库清理相关资源(守护线程)
也就是此时主线程可以和该子线程并发执行 与join相对立
在子线程detach后不能再join回来 会报错
判断是否能使用join或者detach
if(mobj.joinable() == true)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)