thread::join(),函数被调用后,调用它的线程会被block,直到线程执行被完成。
#include <iostream>
#include <thread>
using namespace std;
void func()
{
cout<<"thread is running"<<endl;
}
int main(int argc, char *argv[])
{
thread t(func); //创建线程,一旦创建完毕,马上开始运行。
t.join();
return 0;
}
当需要向线程函数传递参数时,直接在创建线程时,同时也把参数作为入参传递给线程函数。
注意当调用函数的参数为引用参数时,线程调用需要加上ref关键字表示引用,并且线程函数内会改变引用的变量值。
注意:当使用指针或引用向线程函数传参后,如果指针或引用访问的对象已销毁,会造成线程中访问到非法数据。
#include <iostream>
#include <thread>
using namespace std;
void func1(int n)
{
n++;
cout << "n = " << n <<endl;
}
void func2(int &n)
{
n++;
cout << "n = " << n <<endl;
}
int main(int argc, char *argv[])
{
int n = 0;
thread t1(func1, n);
t1.join();
cout << "n = " << n <<endl;
thread t2(func2, ref(n));
t2.join();
cout << "n = " << n <<endl;
return 0;
}
#include <iostream>
#include <thread>
using namespace std;
class Test
{
public:
void func1(int n)
{
cout << "n = " << n <<endl;
}
static void func2(int n)
{
cout << "static : n = " << n <<endl;
}
};
int main(int argc, char *argv[])
{
Test test;
thread t1(&Test::func1, &test, 2);
t1.join();
thread t2(&Test::func2, 3);
t2.join();
return 0;
}
2、线程操作
thread::join(),当thread::join()返回时,线程已经完成,thread对象可以被销毁。
thread::detach(),函数被调用后,执行的线程从线程对象中被分离,已不再被一个线程对象所表达--这是两个独立的事情。C++线程对象可以被销毁,同时OS执行的线程可以继续。如果程序想要知道执行的线程何时结束,就需要一些其它的机制。当主进程结束的时候,detach()出去的子线程不管有没有完成都会被强制杀死。join()函数在那个thread对象上不能再被调用,因为它已经不再和一个执行的线程相关联。
在thread对象析构前,必须要调用join、detach中任意一个。
线程管理对象thread与线程,最初由t1管理线程,然后通过move()将t1管理的线程移交给t2,此时线程还是同一个,只是所属权发生改变。
在t1建立时,线程开始执行,在move()移交过程中,其执行不受影响。
由于t1已不再管理线程,故t1不需要调用join或detach,让t1自动析构就行;
t2获得线程管理权,故t2需要调用join等待线程执行结束。
#include <iostream>
#include <thread>
using namespace std;
void func()
{
cout<<"thread id : " << this_thread::get_id() <<endl;
}
int main(int argc, char *argv[])
{
thread t1(func);
thread t2(move(t1));
t2.join();
return 0;
}
先等待t1线程执行完毕,然后t2,t3,t4三个线程被调度,交替执行,所以结果比较混乱。
#include <iostream>
#include <thread>
using namespace std;
void func(int n)
{
cout<<"thread " << n << " is running" <<endl;
}
int main(int argc, char *argv[])
{
thread t1(func, 1);
t1.join();
thread t2(func, 2);
thread t3(func, 3);
thread t4(func, 4);
t2.join();
t3.join();
t4.join();
return 0;
}
detach操作可以将线程分离,允许线程独立执行。等到线程执行完毕后,系统会自动将资源回收。
由于线程已脱离t1控制,故t1无需调用join或detach,让t1自动析构就行。
#include <iostream>
#include <thread>
using namespace std;
void func()
{
cout<<"thread is running" <<endl;
}
int main(int argc, char *argv[])
{
thread t1(func);
t1.detach();
return 0;
}
3、线程停止
一般情况下当线程函数执行完成后,线程“自然”停止。但在std::thread中有一种情况会造成线程异常终止,那就是:析构。
当std::thread实例析构时,如果线程还在运行,则线程会被强行终止掉,这可能会造成资源的泄漏,因此尽量在析构前join一下,以确保线程成功结束。
如果确实想提前让线程结束怎么办呢?一个简单的方法是使用“共享变量”,线程定期地去检测该量,如果需要退出,则停止执行,退出线程函数。
使用“共享变量”需要注意,在多核、多CPU的情况下需要使用“原子”操作。
参考链接:
https://www.cnblogs.com/corineru/p/10847394.html
若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!
同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。
本文涉及工程代码,公众号回复:01Thread,即可下载。