目录
thread.h
声明thread类和this_thread命名空间的头文件
class thread
表示各个执行线程。
执行线程是一个指令序列,它可以在多线程环境中与其他这样的序列同时执行,同时共享相同的地址空间。
一个初始化的线程对象表示一个正在执行的活动线程;这样的线程对象是可接合的,并且具有唯一的线程id。
默认构造的(未初始化的)线程对象是不可接合的,它的线程id是所有不可接合线程的通用id。
如果从可接合线程移动,或者在它们上调用join或detach,可接合线程将变得不可接合。
成员类型:id 和 native_handle_type
id
这种类型的值由thread::get_id和this_thread::get_id返回,用来标识线程。
默认构造的thread::id对象的值标识不可连接的线程,因此与任何此类线程的成员thread::get_id返回的值比较。
对于可接合线程,thread::get_id返回该类型的唯一值,与其他可接合或不可接合线程的返回值不相等。
注意,某些库实现可能会重新利用终止线程的thread::id值,该线程不能再被连接。
noexcept id ();/ /默认构造函数
构造thread::id值,表示所有不可连接的线程。
id对象是可以复制的
typedef /* implementation-defined */ native_handle_type;
本地句柄类型,只有库实现支持该成员类型时,该成员类型才会出现在类thread中。
它是thread::native_handle返回的类型,带有关于线程的具体实现信息。
成员函数
构造函数
default (1) | thread() noexcept; |
initialization (2) | template <class Fn, class... Args> |
copy [deleted] (3) | thread (const thread&) = delete; |
move (4) | thread (thread&& x) noexcept; |
构造一个线程对象:
(1)默认构造函数
构造不表示任何执行线程的线程对象。
(2)初始化的构造函数
构造一个线程对象,表示一个新的可接合的执行线程。新的执行线程调用fn,将args作为参数传递(使用其左值或右值引用的衰减副本)。该构造的完成与fn副本的调用开始同步。
(3)拷贝构造函数
删除构造函数形式(线程对象不能被复制)。
(4)移动构造函数
构造一个thread对象,获取由x表示的执行线程(如果有的话)。这个操作不会以任何方式影响移动线程的执行,它只是传输它的处理程序。x对象不再代表任何执行线程。可接合的线程对象应该在销毁之前被接合或分离。
fn - 指向函数的指针,指向成员的指针,或任何一种可移动构造的函数对象(即,其类定义了operator()的对象,包括闭包和函数对象)。返回值(如果有的话)会被忽略。
args…… - 传递给fn调用的参数(如果有的话)。它们的类型应是可移动构造的。如果fn是一个成员指针,第一个参数应该是一个定义了该成员的对象(或者引用,或者指向该成员的指针)。
x - 将其状态移动到已构造对象的线程对象。
Fn和Args……是模板形参:如果是隐式推断的,则它们是参数绑定的合适左值或右值引用类型。但是请注意,在新线程中调用fn时,fn和args的衰减副本…总是使用(请参阅std::ref以获得使引用可复制的包装器类)。
初始化构造函数(2)在以下条件下抛出异常:
如果它生成的任何副本(Fn和Args…的衰减类型)的构造抛出,它也抛出。
根据库的实现,这个构造函数还可以抛出异常来报告其他情况(例如bad_alloc或带有其他错误条件的system_error)。
注意,如果函数调用(即fn本身)抛出异常,则由新线程处理。如果此调用以未捕获的异常终止,则调用terminate()。
析构函数
~thread();
销毁线程对象。如果撤销时线程是可接合的,则调用terminate()。
操作符重载:std::thread::operator=
move (1) | thread& operator= (thread&& rhs) noexcept; |
copy [deleted] (2) | thread& operator= (const thread&) = delete; |
Move-assign线程
如果对象当前是不可连接的,它将获得rhs表示的执行线程(如果有的话)。
如果它是可接合的,则调用terminate()。
调用之后,rhs不再表示任何执行线程(就像默认构造的线程一样)。
线程对象不能被复制(2)。
rhs - thread object whose state is moved to *this.
获取线程id
id get_id() const noexcept;
返回线程id。
如果线程对象是可接合的,函数返回唯一标识线程的值。
如果线程对象是不可连接的,该函数返回一个默认构造的成员类型为thread::id的对象。
No-throw保证:从不抛出异常。
检查是否可接合的
bool joinable() const noexcept;
返回线程对象是否可接合。
如果线程对象表示一个执行线程,那么它是可接合的。
线程对象在以下任何一种情况下都是不可连接的:
- 如果它是默认构造的。
- 如果它已被移动(构造另一个线程对象,或对其进行赋值)。
- 如果它的任何一个成员被调用join或detach。
连接线程
void join();
当线程执行完成时,函数返回。
这将在函数返回的时刻与线程中所有操作的完成同步:这将阻塞调用该函数的线程的执行,直到被调用的构造函数返回(如果它还没有返回)。
调用此函数后,线程对象变得不可接合,可以安全地销毁。
完成对象的修改。
注意,线程对象本身的任何操作都是不同步的(与它所代表的线程内的操作不同)。
异常:
基本保证:如果这个成员函数抛出异常,线程对象将保持有效状态。
如果调用失败,抛出一个system_error异常:
请注意,如果对象表示的线程以未捕获的异常终止,当前线程无法捕获该异常,并自动调用terminate()。
分离线程
void detach();
将对象表示的线程与调用线程分离,允许它们彼此独立地执行。
两个线程继续运行,不会阻塞也不会以任何方式同步。注意,当其中一个结束执行时,它的资源将被释放。
调用此函数后,线程对象变得不可接合,可以安全地销毁。
异常:
基本保证:如果这个成员函数抛出异常,线程对象将保持有效状态。
如果调用失败,抛出一个system_error异常:
交换线程
void swap (thread& x) noexcept;
用x的状态交换对象的状态。
x - 线程对象,其状态被交换为*this的状态。
获取本地处理
native_handle_type native_handle ();
只有库实现支持时,这个成员函数才会出现在类thread中。
如果存在,则返回一个用于访问与线程相关的特定于实现的信息的值。
检测硬件并发
static unsigned hardware_concurrency() noexcept;
返回硬件线程上下文的数目。
对这个值的解释是特定于系统和实现的,可能不精确,但只是一个近似。
注意,这并不需要与系统中可用的处理器或内核的实际数量匹配:一个系统可以支持每个处理单元多个线程,或者限制程序对其资源的访问。
如果此值不可计算或定义不当,则函数返回0。
返回值
关于硬件线程上下文数量的提示。
如果该值不可计算或定义不明确,则为零。
交换线程(非成员重载)
void swap (thread& x, thread& y) noexcept;
交换线程对象x和y的状态。
这是一个swap重载,其行为就像调用了x.swap(y)。
x, y - 交换的线程对象。
namespace std::this_thread
这个名称空间将一组访问当前线程的函数分组。
- get_id
获取线程id,返回调用线程的线程id。
这个值唯一地标识线程。
- yield
void yield() noexcept;
让步于其他线程,调用线程产生,为实现提供了重新调度的机会。
当一个线程等待其他线程在不阻塞的情况下前进时,将调用这个函数。
- sleep_until
template <class Clock, class Duration>
void sleep_until (const chrono::time_point<Clock,Duration>& abs_time);
Sleep 直到指定时间点,阻塞调用线程直到abs_time。
当前线程的执行至少停止到abs_time,而其他线程可以继续前进。
- sleep_for
template <class Rep, class Period>
void sleep_for (const chrono::duration<Rep,Period>& rel_time);
Sleep 指定时间跨度
在rel_time指定的时间范围内阻塞调用线程的执行。当前线程的执行将停止,直到至少rel_time已经通过。其他线程继续执行。