1.创建线程对象
1)不代表任何执行线程的对象
thread() noexcept;
2)fn为可调用对象(函数、仿函数(重载()运算符的类),初始化为"class()")、lame表达式)。args为与之同步的一包参数列表
【备注】:类的成员函数作为可调用对象时,第一参数必须是该成员函数的地址,第二参数应为该类。 仿函数作为可调用对象时,第二参数必须是仿函数类名+()。
template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);
3)无线程thread的拷贝、赋值语义
thread (const thread&) = delete;
thread& operator=(const thread&) = delete;
4)线程thread的move语义,swap也理解为move语义
thread (thread&& x) noexcept;
thread& operator=(thread&& _Other) noexcept;
void swap(thread& _Other) noexcept;
2.等待线程完成函数
void join();
3.分离线程函数
void detach();
4.判断当前线程是否是可执行线程(是否可以被join和detach)
bool joinable();
【备注】:
1)由"thread()"版本构造函数创建的、thread对象被move过(包括move构造和move赋值)、并且该线程被join或者detach过,都不是可执行线程thread。
2)表示具体执行线程thread,有且仅有一次被join和detach。多次调用或出作用域一次没调用程序出错。
5.线程传参args
1)函数形参类型:传值、引用、常引用、传指针。
void fun(const T& arg1,T& arg2);
2)创建线程实参类型:一般类型(int等)、类、存在隐式类型转换(如int->class)、std::ref(T)、指针。
小结:
1)有且仅有可调用对象形参为引用,例如:void fun(const T& arg1,T& arg2);
,并且实参经过std::ref转换,例如:std::thrad(fun,std::ref(arg1),std::ref(arg2));
,才实现真正的引用。否则编译报错或者未实现引用(主线程或子线程中至少做一次拷贝)。
2)堆为线程共享空间,传值指针为经典的多线程维护堆空间问题。
3)还可使用move,实现move语义。
6.线程id
获取方式一:myThread.get_id(); 获取线程对象myThread的id
获取方式二:std::this_thread::get_id(); 获取当前线程id
7.硬件支持的并发线程数
可以用以控制同时段都有运行的线程和硬件线程数量(同一时刻运行的线程最大数量)的关系,防止超额订阅,因为上下文切换会降低性能。
static unsigned int hardware_concurrency() noexcept;
8.nativehandle函数允许使用平台API直接操作低层实现
typedef void* native_handle_type;
native_handle_type native_handle()
{ // return Win32 HANDLE as void *
return (_Thr._Hnd);
}
更深入的探讨请参考对我另外一篇博客:https://blog.csdn.net/qq_43148810/article/details/113776245
如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810