翻看代码的时候,std::this_thread::yield()
猛的引入眼帘,C11
里面的语法糖,用了不少,yield
还是第一次看到,以前都没注意。
没查手册,首先想到的是不是和异步变成相关,yield
boost库的协程实现里面用到了这个单词,这里肯定和协程没关系,控制逻辑和普通线程相关。
文档
yield
此函数的准确性为依赖于实现,特别是使用中的 OS 调度器机制和系统状态。例如,先进先出实时调度器( Linux 的 SCHED_FIFO )将悬挂当前线程并将它放到准备运行的同优先级线程的队列尾(而若无其他线程在同优先级,则 yield 无效果)
sleep_for
阻塞当前线程执行,至少经过指定的 sleep_duration 此函数可能阻塞长于 sleep_duration ,因为调度或资源争议延迟 标准库建议用稳定时钟度量时长。若实现用系统时间代替,则等待时间亦可能对时钟调节敏感
分析
两个函数都是让当前线程不再占用线程,执行的效果按照平台情况而定?看到这里依旧有点云里雾里的,运行代码看看执行效果
ThinkPad 笔记本(visual studio 社区版2022)、腾讯云S2标准服务器(gcc8.5)
运行平台 | 函数 | 第一次/us | 第二次/us | 第三次/us |
---|---|---|---|---|
Windows | sleep_for | 9872 | 1884 | 11302 |
Windows | yield | 119 | 100 | 100 |
Linux | sleep_for | 171 | 168 | 167 |
Linux | yield | 101 | 102 | 101 |
从运行结果不难理解,由于操作系统实现的不同,高精度的休眠时,sleep_for
稳定性差异巨大,如果想要高精度的休眠,使用yield
更加合适
时间精度提升到ms
时,两者差异并不明显
#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::microseconds(100));
std::this_thread::sleep_for(std::chrono::microseconds(100));
auto elapsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "waited for "
<< std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
<< " microseconds\n";
}