线程的启动,也就是线程入口函数的传递方式。虽然函数接口中有多种形式,可以创建无参对象(线程没有入口函数,也就是线程不做任务),但是这种没有什么意义,一般不使用;可以将两外一个线程对象移动过来,但是移动之后,另外一个线程对象就没有了,这种一般用的也不多,接下来我们重点研究第三种接口形式。
在C++11中,将线程封装成了类的概念,下面就是线程类的构造函数形式。
thread() noexcept; //(1)无参对象
thread( thread&& other ) noexcept; //(2)移动构造
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args ); //(3) 可变参数的形式,f就是线程入口函数,args就是f的传参
// bind也可以传递可变参数
// thread的传参与std::bind的传参类似,所以thread的传参可以传占位符;默认也是采用值传递,如果需要使用引用,可以使用引用的包装器std::ref/std::cref
thread(const thread&) = delete;//(4)没有拷贝构造函数
// 因为线程id是唯一的
如何获取线程id
/*
获取线程id会有成员函数get_id;
可以使用std::this_thread中的函数get_id获取线程id;
*/
创建线程并执行
#include <iostream>
#include <thread>
#include <unistd.h>
using std::thread;
using std::cout;
using std::endl;
void threadFunc(void){
cout << "void threadFunc(void)" << endl;
}
int main(int argc, char * argv[]){
thread myTh(threadFunc); // 创建线程对象
// 1、让主线程睡眠一段时间,让子线程有足够的时间执行
// 2、通过在主线程中添加死循环,让子线程有机会执行
cout << "1111" << endl;
// 3.让主线程等待子线程的执行
myTh.join();
/*
1111
void threadFunc(void)
finish main...
*/
cout << "finish main..." << endl;
/*while(1){}
1111
finish main...
void threadFunc(void)
*/
/*
sleep(10);
1111
void threadFunc(void)
terminate called without an active exception
已中止 (核心已转储)
*/
return 0;
}
C++11 的std::thread
构造函数提供了非常强大和灵活的传参机制,其核心原则是:直接传递,自动转发。
std::thread
的构造函数是一个变长模板,使用完美转发技术。这意味着:
std::thread
的构造函数中即可。std::thread
会尽力保持参数的本意。这是最简单、最安全的方式。参数会被拷贝到线程的内部存储中。
void threadFunc(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
thread myTh(threadFunc,1); // 创建了线程,并且启动入口函数
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果:
main thread id = 128022756660160
child thread id = 128022749378112
child2 thread id = 128022749378112
void thread()
x = 1
finish main...
*/
2.引用传递 (Pass by Reference)
如果你想在线程中修改原始数据,或者避免拷贝大对象,需要使用引用。但必须格外小心!
用法:使用 std::ref() 或 std::cref() 包装器来明确表示要传递引用。
std::ref(arg): 生成一个 arg 的可修改引用包装器。
std::cref(arg): 生成一个 arg 的常量引用(const reference)包装器。
重要警告:你必须确保被引用参数的生存期超过线程的执行时间,否则会导致未定义行为(通常是崩溃)。
void threadFunc(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
// 定义引用类型
typedef void(&rftr)(int);
rftr f = threadFunc;
thread myTh(f,3);
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 134538343646144
child2 thread id = 134538336400960
void thread()
x = 3
child thread id = 134538336400960
finish main...
*/
传递指针本质上是按值传递(传递的是地址这个值)。但和引用一样,存在生命周期和数据竞争的问题。
void threadFunc(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
// 定义函数指针
typedef void(*pFunc)(int); // 定义函数指针
pFunc f = threadFunc; // 函数指针指向threadFunc
thread myTh(f,2); // 创建了线程,并且启动入口函数
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 137969113899968
child thread id = 137969107203648
child2 thread id = 137969107203648
void thread()
x = 2
finish main...
*/
class Example{
public:
void threadFunc(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
};
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
// 联想bind函数
Example ex;
thread myTh(&Example::threadFunc,&ex,4);
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 125797603070912
child thread id = 125797595608640
child2 thread id = 125797595608640
void thread()
x = 4
finish main...
*/
class Example{
public:
void operator()(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
};
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
Example ex;
thread myTh(ex,5);
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果:
main thread id = 126747620344768
child thread id = 126747613853248
child2 thread id = 126747613853248
void thread()
x = 5
finish main...
*/
传递可调用对象 (如 Lambda 表达式)
Lambda 可以捕获局部变量,这是一种非常方便的“传参”方式。
按值捕获:捕获的变量被拷贝到 Lambda 对象中,安全。
按引用捕获:极其危险! 你必须确保被捕获引用的变量生命周期足够长。
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
thread myTh([](int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
},6);
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 125488134484928
child thread id = 125488127276608
child2 thread id = 125488127276608
void thread()
x = 6
finish main...
*/
// 使用函数包装器
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
// 接收lambda的返回值
function<void(int)> f = [](int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
};
thread myTh(f,7);
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 134957241263040
child thread id = 134957234124352
child2 thread id = 134957234124352
void thread()
x = 7
finish main...
*/
void threadFunc(int x){
cout << "child2 thread id = " << std::this_thread::get_id() << endl;
cout << "void thread()" << endl;
cout << "x = " << x << endl;
}
int main(int argc, char * argv[]){
cout << "main thread id = " << std::this_thread::get_id() << endl;
thread myTh(bind(&threadFunc,8));
cout << "child thread id = " << myTh.get_id() << endl;
myTh.join();
cout << "finish main..." << endl;
return 0;
}
/*
输出结果
main thread id = 129025456661440
child thread id = 129025450178112
child2 thread id = 129025450178112
void thread()
x = 8
finish main...
*/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。