线程
线程使得程序能在数个处理器核心同时执行。
thread 类
定义用于查看和管理应用程序中执行线程的对象。
要求
头文件: <thread>
命名空间: std
公共方法
名称 | 描述 |
---|---|
detach | 容许线程从线程句柄独立开来执行 |
get_id | 返回线程的 id |
hardware_concurrency[静态] | 返回实现支持的并发线程数 |
join | 等待线程完成其执行 |
joinable | 检查线程是否可合并,即潜在地运行于平行环境中 |
native_handle | 返回底层实现定义的线程句柄 |
swap | 交换二个 thread 对象 |
join
阻塞当前线程,直至 *this 所标识的线程完成其执行。
*this 所标识的线程的完成同步于从 join() 的成功返回。
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
// 模拟昂贵操作
std::this_thread::sleep_for(1s);
}
void bar()
{
// 模拟昂贵操作
std::this_thread::sleep_for(1s);
}
int main()
{
std::cout << "启动第一个辅助线程...\n";
std::thread helper1(foo);
std::cout << "启动第二个辅助线程...\n";
std::thread helper2(bar);
std::cout << "正在等待辅助线程完成..." << std::endl;
helper1.join();
helper2.join();
std::cout << "完成!\n";
}
Output |
---|
启动第一个辅助线程... 启动第二个辅助线程... 正在等待辅助线程完成... 完成! |
detach
从 thread 对象分离执行的线程,允许执行独立地持续。一旦线程退出,则释放所有分配的资源。
调用 detach 后, *this 不再占有任何线程。
#include <iostream>
#include <chrono>
#include <thread>
void independentThread()
{
std::cout << "正在启动并发线程。\n";
std::this_thread::sleep_for(2s);
std::cout << "正在退出并发线程。\n";
}
void threadCaller()
{
std::cout << "正在启动线程调用者。\n";
std::thread t(independentThread);
t.detach(); // 调用detach后,即使当前函数返回依旧可以继续执行
std::this_thread::sleep_for(1s);
std::cout << "正在退出线程调用者.\n";
}
int main()
{
threadCaller();
std::this_thread::sleep_for(10s);
}
Output |
---|
正在启动线程调用者。 正在启动并发线程。 正在退出线程调用者. 正在退出并发线程。 |
get_id
返回标识与 *this 关联的线程的 std::thread::id 类型值。
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(1s);
}
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 << "线程1 id: " << t1_id << '\n';
std::cout << "线程2 id: " << t2_id << '\n';
t1.join();
t2.join();
}
Output |
---|
线程1 id: 17068 线程2 id: 28460 |
joinable
检查 thread 对象是否标识活跃的执行线程。具体是返回 true if get_id() != std::thread::id() 。故默认构造的 thread 不可合并。
完成执行代码,但未被合并的线程仍被认为是活跃线程,从而可合并。
#include <iostream>
#include <thread>
#include <chrono>
#include <iomanip>
using namespace std;
void foo()
{
this_thread::sleep_for(1s);
}
int main()
{
cout << left << boolalpha;
thread t;
cout << "线程启动前" << " id:" << setw(5) << t.get_id() << " joinable: " << t.joinable()
<< '\n';
t = thread(foo);
cout << "线程启动后" << " id:" << setw(5) << t.get_id() << " joinable: " << t.joinable()
<< '\n';
t.join();
cout << "线程加入后" << " id:" << setw(5) << t.get_id() << " joinable: " << t.joinable()
<< '\n';
}
Output |
---|
线程启动前 id:0 joinable: false 线程启动后 id:8800 joinable: true 线程加入后 id:0 joinable: false |
hardware_concurrency
返回实现所支持的并发线程数。应该只把值当做提示。
#include <iostream>
#include <thread>
int main() {
unsigned int n = std::thread::hardware_concurrency();
std::cout <<"支持 "<< n << " 个并发线程。\n";
}
Output |
---|
支持 8 个并发线程。 |
管理当前线程的函数
定义于命名空间 this_thread
名称 | 描述 |
---|---|
yield | 建议实现重新调度各执行线程 |
get_id | 返回当前线程的线程 id |
sleep_for | 使当前线程的执行停止指定的时间段 |
sleep_until | 使当前线程的执行停止直到指定的时间点 |
this_thread::yield
提供提示给实现,以重调度线程的执行,允许其他线程运行。
#include <iostream>
#include <chrono>
#include <thread>
// 建议其他线程运行一小段时间的“忙睡眠”
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() < end);
}
int main()
{
auto start = std::chrono::high_resolution_clock::now();
little_sleep(std::chrono::milliseconds(100)); // 睡眠100毫秒
auto elapsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "等待了 "
<< std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()
<< " 毫秒\n";
}
Output |
---|
等待了 100 毫秒 |
this_thread::get_id
返回当前线程的 id 。
#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
std::mutex g_display_mutex;
void foo()
{
std::thread::id this_id = std::this_thread::get_id();
g_display_mutex.lock();
std::cout << "线程 " << this_id << " 睡眠中...\n";
g_display_mutex.unlock();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t1(foo);
std::thread t2(foo);
t1.join();
t2.join();
}
Output |
---|
线程 26088 睡眠中... 线程 3752 睡眠中... |
this_thread::sleep_for
阻塞当前线程执行,至少经过指定的 sleep_duration 。
此函数可能阻塞长于 sleep_duration ,因为调度或资源争议延迟。
标准库建议用稳定时钟度量时长。若实现用系统时间代替,则等待时间亦可能对时钟调节敏感。
#include <iostream>
#include <chrono>
#include <thread>
int main()
{
using namespace std::chrono_literals; // C++14
std::cout << "Hello waiter" << std::endl; // 有意冲入
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_for(2s); // 等待2秒(2秒=2000毫秒)
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = end - start;
std::cout << "Waited " << elapsed.count() << " ms\n";
}
Output |
---|
Hello waiter Waited 2000.49 ms |