std::thread是C++11中提供多线程编程模块。使用时需要包含<thread>头文件。
简单说一下thread的用法
1 构造函数
构造函数是构造thread对象的,thread只是一个管理线程的类,并不是所有的thread对象都绑定一个实际的可执行的线程。也就是说有的thread对象并没有创建一个可执行的线程。
构造函数 | 函数 |
---|---|
default(1) | thread() noexcept |
initialization (2) | template <class Fn, class… Args> explicit thread (Fn&& fn, Args&&… args); |
copy [deleted] (3) | thread (const thread&) = delete; |
move (4) | thread (thread&& x) noexcept; |
1、默认构造函数
// 示例代码
std::thread t;
默认构造函数是单纯地构造一个thread对象,并没有绑定一个可执行线程,也就是说并没有创建一个线程。
2、初始化构造函数
构造一个表示新的可执行线程的thread对象。新的可执行线程调用fn函数,args作为函数的参数。
构造对象的完成是与fn函数的副本的调用时同步的。
其实就是重载构造函数,有传递线程函数和函数参数,这种构造函数直接创建一个线程,并默认开始执行函数。
// 示例代码
#include <iostream>
#include <thread>
using namespace std
void func()
{
cout << "Thread is running !" << endl;
}
int main()
{
thread t(func);
getchar();
}
运行结果如下:
当然上面代码还有一点小问题,正常执行后当程序退出时会出现如下错误:
这是因为并没有设定新创建的线程与当前线程在销毁时的方式,这个在后面会详细叙述。
3、拷贝构造函数
拷贝构造函数是被禁用的,也就是说thread对象是不支持复制的
4、移动构造函数
构造一个thread对象,该对象获取x(是另一个thread对象)所管理的可执行线程。这个操作并不影响线程的执行。它只是简单了更改了线程的所有者。从而x不再具有管理原来线程的能力,即不代表原来的线
可joinable的thread对象在被销毁之前,需要被joined或者detached。 这也是为什么在2中会出现相应的错误。
这里解释一下joinable,join,detach
joinable
joinable是thread对象的一个属性。如果一个thread对象代表一个可执行线程则该线程是joinable的,一个thread对象在一下三种情况下是非joinable的:
a、如果该对象是用默认构造函数构造的
b、如果该对象的线程被移动到其他对象了,也就是被当作参数传递给move构造函数。
c、如果该对象已经调用过join或者detach。
joined和detched
join和detach是协调主线程和被创建的子线程之间的同步关系的两种方式。
join()直到thread对象所管理的线程执行结束后才会返回。
detach()函数立刻返回。
所以当调用join()则表示主线程和子线程属于同步状态,当调用detach()则表示主线程和子线程属于异步状态。示例如下:
#include <tuple>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void func1()
{
this_thread::sleep_for(chrono::milliseconds(2000));
cout << "Thread1 is running !" << endl;
}
void func2()
{
this_thread::sleep_for(chrono::milliseconds(3000));
cout << "Thread2 is running !" << endl;
}
int main()
{
thread t1(func1);
thread t2(func2);
t1.join();
t2.detach();
cout << "Main thread is running !" << endl;
getchar();
}
结果如下:
从结果很容易可以看出join()和detach()的区别。t1.join()时主线程阻塞。知道t1线程运行完毕,到t2.detach(),主线程和t2运行互不干涉。
2 其他成员函数
get_id()
获取线程的id
joinable()
判断是否可joinable
join()
该函数当线程执行完毕则返回。该函数同步了函数返回和线程中所有操作完成的时刻。该函数会阻塞调用该函数的线程。
当调用该函数后,thread对象则为non-joinable,同时该线程可以安全地被销毁。
detach()
使调用该函数的线程和thread对象所代表的线程分离,使他们可以独立的执行。
两个线程都不会被阻塞,也没有任何同步。不过这里要注意如果thread对象是在当前线程中创建的,那么需要注意当前线程只想完毕后会销毁thread对象。所以有可能出现thread仍在执行,但是thread对象被销毁的情况。
该函数被调用后,thread对象变为non-joinable,并且可以被安全销毁。