c++ 11 之后有了标准的线程库:std::thread。
之前一些编译器使用 C++11 的编译参数是 -std=c++11
g++ -std=c++11 test.cpp
std::thread 构造函数
默认构造函数 | thread() noexcept; |
---|---|
初始化构造函数 |
template explicit thread(Fn&& fn, Args&&… args); |
拷贝构造函数 [deleted] | thread(const thread&) = delete; |
Move 构造函数 | thread(thread&& x) noexcept; |
- 默认构造函数,创建一个空的
std::thread
执行对象。 - 初始化构造函数,创建一个
std::thread
对象,该std::thread
对象可被joinable
,新产生的线程会调用fn
函数,该函数的参数由args
给出。 - 拷贝构造函数(被禁用),意味着
std::thread
对象不可拷贝构造。 - Move 构造函数,move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后
x
不代表任何std::thread
执行对象。
注意:可被
joinable
的std::thread
对象必须在他们销毁之前被主线程join
或者将其设置为detached
.
std::thread 各种构造函数例子如下:
#include#include #include #include #include #include void f1(int n) { for (int i = 0; i std::thread 赋值操作
Move 赋值操作 thread& operator=(thread&& rhs) noexcept; 拷贝赋值操作 [deleted] thread& operator=(const thread&) = delete;
- Move 赋值操作(1),如果当前对象不可
joinable
,需要传递一个右值引用(rhs
)给move
赋值操作;如果当前对象可被joinable
,则会调用terminate
() 报错。- 拷贝赋值操作(2),被禁用,因此
std::thread
对象不可拷贝赋值。请看下面的例子:
#include#include #include // std::chrono::seconds #include // std::cout #include // std::thread, std::this_thread::sleep_for void thread_task(int n) { std::this_thread::sleep_for(std::chrono::seconds(n)); std::cout 其他成员函数
get_id: 获取线程 ID,返回一个类型为 std::thread::id 的对象。请看下面例子:
#include#include #include void foo() { std::this_thread::sleep_for(std::chrono::seconds(1)); } int main() { std::thread t1(foo); std::thread::id t1_id = t1.get_id(); std::thread t2(foo); std::thread::id t2_id = t2.get_id(); std::cout joinable: 检查线程是否可被 join。检查当前的线程对象是否表示了一个活动的执行线程,由默认构造函数创建的线程是不能被 join 的。另外,如果某个线程 已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,因此也是可以被 join 的。
#include#include #include void foo() { std::this_thread::sleep_for(std::chrono::seconds(1)); } int main() { std::thread t; std::cout #include #include void foo() { // simulate expensive operation std::this_thread::sleep_for(std::chrono::seconds(1)); } void bar() { // simulate expensive operation std::this_thread::sleep_for(std::chrono::seconds(1)); } int main() { std::cout detach: Detach 线程。 将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。
调用 detach 函数之后:
*this
不再代表任何的线程执行实例。- joinable() == false
- get_id() == std::thread::id()
另外,如果出错或者 joinable() == false,则会抛出 std::system_error。
#include#include #include void independentThread() { std::cout swap: Swap 线程,交换两个线程对象所代表的底层句柄(underlying handles)。
#include#include #include void foo() { std::this_thread::sleep_for(std::chrono::seconds(1)); } void bar() { std::this_thread::sleep_for(std::chrono::seconds(1)); } int main() { std::thread t1(foo); std::thread t2(bar); std::cout 执行结果如下:
thread 1 id: 1892 thread 2 id: 2584 after std::swap(t1, t2): thread 1 id: 2584 thread 2 id: 1892 after t1.swap(t2): thread 1 id: 1892 thread 2 id: 2584native_handle: 返回 native handle(由于 std::thread 的实现和操作系统相关,因此该函数返回与 std::thread 具体实现相关的线程句柄,例如在符合 Posix 标准的平台下(如 Unix/Linux)是 Pthread 库)。
#include#include #include #include #include std::mutex iomutex; void f(int num) { std::this_thread::sleep_for(std::chrono::seconds(1)); sched_param sch; int policy; pthread_getschedparam(pthread_self(), &policy, &sch); std::lock_guard<:mutex> lk(iomutex); std::cout 执行结果如下:
Thread 2 is executing at priority 0 Thread 1 is executing at priority 20
hardware_concurrency [static]: 检测硬件并发特性,返回当前平台的线程实现所支持的线程并发数目,但返回值仅仅只作为系统提示(hint)。
#include#include int main() { unsigned int n = std::thread::hardware_concurrency(); std::cout std::this_thread 命名空间中相关辅助函数介绍
get_id: 获取线程 ID。
#include#include #include #include std::mutex g_display_mutex; void foo() { std::thread::id this_id = std::this_thread::get_id(); g_display_mutex.lock(); std::cout yield: 当前线程放弃执行,操作系统调度另一线程继续执行。
#include#include #include // "busy sleep" while suggesting that other threads run // for a small amount of time void little_sleep(std::chrono::microseconds us) { auto start = std::chrono::high_resolution_clock::now(); auto end = start + us; do { std::this_thread::yield(); } while (std::chrono::high_resolution_clock::now() (elapsed).count() sleep_until: 线程休眠至某个指定的时刻(time point),该线程才被重新唤醒。
template void sleep_until( const std::chrono::time_point& sleep_time ); sleep_for: 线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比 sleep_duration 所表示的时间片更长。
#include#include #include int main() { std::cout 执行结果如下:
Hello waiter Waited 2000 ms来源:https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter3-Thread/Introduction-to-Thread.md
评论(0)