std::thread类来表示执行的各个线程。
执行线程是实际上是执行一系列指令,可以在多线程环境中与其他此类序列同时执行,同时共享相同的地址空间。
一个初始化的线程(std::thread)对象表示活动的执行线程,即初始化后std::thread立即运行;这样的线程对象是可连接的(joinable),并且具有唯一的线程id。
默认构造的(未初始化的)线程对象是不可连接的(not joinable),其线程id对于所有不可连接线程都是通用的。
如果move线程,或者对它们调用join或detach,则可连接线程将变得不可连接。
(1)thread成员变量:
id
Thread id (public member type)
native_handle_type
Native handle type (public member type)
(2)thread成员函数:
(constructor)
Construct thread (public member function)
(destructor)
Thread destructor (public member function)
operator=
Move-assign thread (public member function)
get_id
Get thread id (public member function)
joinable
Check if joinable (public member function)
join
Join thread (public member function)
detach
Detach thread (public member function)
swap
Swap threads (public member function)
native_handle
Get native handle (public member function)
hardware_concurrency [static]
Detect hardware concurrency (public static member function)
以下为thread主要的成员函数使用介绍。
bool joinable() const noexcept;
检查线程是否可连接,返回线程对象是否可连接。
(1)如果线程对象表示执行线程,则它是可连接的。
(2)在以下任何情况下,线程对象都不可连接:
如果它是默认构造的。
如果它已被move(构造另一个线程对象,或分配给另一个线程)。
如果已调用其成员join或detach。
void join();
连接(join)线程,当线程执行完成时,函数返回。
join()函数能够保证调用线程和被调用线程同步,join()函数将阻塞调用该join()函数线程的执行,直到被调用线程的函数返回。调用join()函数后,线程对象变得不可连接,可以安全销毁。
void detach();
分离(detach)线程将对象表示的线程与调用线程分离,允许它们彼此独立地执行。
这两个线程都继续运行,不会以任何方式阻塞或同步。请注意,当其中一方结束执行时,其资源将被释放。调用此函数后,线程对象变得不可连接,可以安全销毁。
void swap (thread& x) noexcept;
交换线程,将对象的状态与x的状态交换。
swap函数与thread的移动构造函数和移动赋值函数作用一样。
thread::thread
Constructthread (public member function)
thread::operator=
Move-assignthread (public member function)
default (1) |
thread() noexcept; |
initialization (2) |
template |
copy [deleted] (3) |
thread (const thread&) = delete; |
move (4) |
thread (thread&& x) noexcept; |
由以上可知,拷贝构造函数已经delete,构造函数中只有三种构造函数可用:
(1) 默认构造函数
构造一个不表示任何执行线程的线程对象。
(2) 初始化构造函数
构造一个线程对象,该对象表示新的可连接执行线程。
新的执行线程调用fn函数传递args 作为参数。
此构造的完成与fn函数的调用开始同步。
(3) 移动构造函数
构造一个线程对象,该对象获取由x表示的执行线程(如果有)。此操作不会以任何方式影响已移动线程的执行,它只是传输其处理程序。之后x对象不再表示任何执行线程。
move (1) |
thread& operator= (thread&& rhs) noexcept; |
copy [deleted] (2) |
thread& operator= (const thread&) = delete; |
Thread赋值函数的拷贝赋值函数已经delete,只有移动赋值函数可用,参数为右值thread,也叫移动分配线程函数。
如果对象当前不可连接,它将获取由rhs表示的执行线程(如果有的话)。
如果它是可连接的,则调用terminate()。
在调用之后,rhs不再表示任何执行线程(就像默认构造的一样)。
// thread example
#include // std::cout
#include // std::thread
void foo()
{
// do stuff...
}
void bar(int x)
{
// do stuff...
}
int main()
{
std::thread first (foo); // spawn new thread that calls foo()
std::thread second (bar,0); // spawn new thread that calls bar(0)
std::cout << "main, foo and bar now execute concurrently...\n";
// synchronize threads:
first.join(); // pauses until first finishes
second.join(); // pauses until second finishes
std::cout << "foo and bar completed.\n";
return 0;
}
输出:
main, foo and bar now execute concurrently... foo and bar completed. |
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
#include // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for (std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended\n";
}
int main()
{
std::cout << "Spawning and detaching 3 threads...\n";
std::thread (pause_thread,1).detach();
std::thread (pause_thread,2).detach();
std::thread (pause_thread,3).detach();
std::cout << "Done spawning threads.\n";
std::cout << "(the main thread will now pause for 5 seconds)\n";
// give the detached threads time to finish (but not guaranteed!):
pause_thread(5);
return 0;
}
输出(5秒后):
Spawning and detaching 3 threads... Done spawning threads. (the main thread will now pause for 5 seconds) pause of 1 seconds ended pause of 2 seconds ended pause of 3 seconds ended pause of 5 seconds ended |
// example for thread::operator=
#include // std::cout
#include // std::thread, std::this_thread::sleep_for
#include // std::chrono::seconds
void pause_thread(int n)
{
std::this_thread::sleep_for (std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended\n";
}
int main()
{
std::thread threads[5]; // default-constructed threads
std::cout << "Spawning 5 threads...\n";
for (int i=0; i<5; ++i)
threads[i] = std::thread(pause_thread,i+1); // move-assign threads
std::cout << "Done spawning threads. Now waiting for them to join:\n";
for (int i=0; i<5; ++i)
threads[i].join();
std::cout << "All threads joined!\n";
return 0;
}
输出(5秒后):
Spawning 5 threads... Done spawning threads. Now waiting for them to join: pause of 1 seconds ended pause of 2 seconds ended pause of 3 seconds ended pause of 4 seconds ended pause of 5 seconds ended All threads joined! |
此命名空间提供了访问当前线程的一组函数。
get_id
获得当前线程id
yield
将当前线程时间片让渡给其他线程
sleep_until
当前线程休眠直到某个时间点
sleep_for
当前线程休眠一段时间
// this_thread::sleep_for example
#include // std::cout, std::endl
#include // std::this_thread::sleep_for
#include // std::chrono::seconds
int main()
{
std::cout << "countdown:\n";
for (int i=10; i>0; --i) {
std::cout << i << std::endl;
std::this_thread::sleep_for (std::chrono::seconds(1));
}
std::cout << "Lift off!\n";
return 0;
}
输出(10秒后):
countdown: 10 9 8 7 6 5 4 3 2 1 Lift off! |