C++ 创建线程的常见方式
C++ 创建线程需要 #include<thread>
1. 普通函数创建
#include <iostream>
#include <thread>
void func()
{
std::cout << "func" << std::endl;
}
int main()
{
std::thread thread(func);
// thread.join(); // join 方法会等到线程执行完毕在继续执行 thread.join 之后的内容
thread.detach(); // detach 线程分离方法,主线程和子线程分离,不会阻塞
// sleep(2); // 如果 func 线程种需要运行很长时间,并采取了detach 方法,当主线程
// 过早结束,子线程会终止,所以需要确保主线程在子线程结束之后再结束
}
2. lambda 函数创建
int a = 10;
std::thread t([a](int b){
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << "lambda" << std::endl;
}, 100);
3. 一个类创建一个线程
- 在使用类创建线程的时候需要注意的是,线程中对类的拷贝次数
#include <iostream>
#include <thread>
#include <unistd.h>
class back_ground
{
public:
int id;
back_ground(int i): id(i)
{
std::cout << "back_ground()" <<std::endl;
}
back_ground(const back_ground& b)
{
std::cout << "&back_ground()" << std::endl;
id = b.id + 10;
}
void operator()() const // 符号重载 ()
{
std::cout << "operator()(), id: " << id << std::endl;
}
void do_something()
{
std::cout << "do_something(), id: " << id << std::endl;
}
~back_ground()
{
std::cout << "~back_ground(), id: " << id << std::endl;
}
};
int main()
{
back_ground b(3);
// 1. 构造std::thread对象时:如果不带参则会创建一个空的thread对象,但底层线程并没有真正被创建,一般可将其他std::thread对象通过move移入其中;如果带参则会创建新线程,而且会被立即运行。
// 2. 在创建thread对象时,std::thread构建函数中的所有参数均会按值并以副本的形式保存成一个tuple对象。该tuple由调用线程(一般是主线程)在堆上创建,并交由子线程管理,在子线程结束时同时被释放。
// 3. std:thread t1(b) 调用拷贝构造函数2次, t1(b) 调用一次拷贝构造, std::thread在构造时,建立tuple对象,tuple对象内部_Tuple_val进行了Ta对象的拷贝
// 不同的编译器有不同的实现,gcc中会拷贝两次,msvc只拷贝一次
std::thread t1(b);
// std::thread t1(&back_ground::do_something, b); // 和 std::thread t1(b) 一样执行两次构造
t1.join();
std::cout << "---------" << std::endl;
}
/* out:
back_ground() // 1. back_ground b(3) 构造函数, id = 3
&back_ground() // 2. t1(b) 第一次调用拷贝构造,id = 3 + 10 = 13
&back_ground() // 3. t2(b) 第二次调用拷贝构造,id = 13 + 10 = 23
~back_ground(), id: 13 // 4. 析构第一次调用拷贝构造的 back_ground 类
operator()(), id: 23 // 5. 执行函数重载的函数
~back_ground(), id: 23 // 6. 析构第二次调用拷贝构造的 back_ground 类
--------- // 7. t.join,线程执行完毕,回到main函数
~back_ground()3 // 7. 最初的构造的类的析构
*/
Tips
获取当前硬件的核心数
std::thread::hardware_concurrency() // 获取cpu的核心数,获取不到的时候返回0
获取线程id
std::thread::get_id() // 线程类获取线程 id
std::this_thread::get_id() // 在线程内部获取线程 id