std::this_thread::yield()实际耗时远低于预期的技术疑问
为什么std::this_thread::yield()循环调用100次耗时远低于预期?
核心原因分析
yield()的本质是“礼让”而非“放弃时间片”
在Windows平台,std::this_thread::yield()底层调用的是SwitchToThread()API。该函数仅会让操作系统尝试调度当前处于就绪状态的其他线程执行;如果系统中没有可调度的其他线程,当前线程会立刻恢复运行,不会等待剩余时间片耗尽。它的作用是主动给其他线程让路,而非强制消耗自身时间片。测试场景无其他就绪线程
你的测试程序中,主线程启动thread_2后立刻调用system("pause")进入暂停状态,此时系统内几乎没有其他就绪线程需要调度。每次调用yield()时,操作系统找不到可切换的目标线程,当前线程直接继续执行循环,因此总耗时微乎其微。对CPU时间片的误解
Windows的CPU时间片是线程连续运行的最大时长,只有当线程运行满时间片、主动进入阻塞状态(如等待IO、调用sleep)时,才会被调度器强制切换。yield()属于主动礼让行为,不属于阻塞,不会触发时间片的消耗逻辑。
验证修改建议
如果想看到yield()的实际切换耗时,可以修改测试程序,让系统存在其他就绪线程:
#include <iostream> #include <thread> #include <windows.h> using namespace std; void thread_function_2() { double dt; LARGE_INTEGER nFreq; QueryPerformanceFrequency(&nFreq); LARGE_INTEGER tstart; LARGE_INTEGER tend; QueryPerformanceCounter(&tstart); for (int a =0; a< 100; a++) { std::this_thread::yield(); } QueryPerformanceCounter(&tend); cout << "-----------------hit 100 times yield cost time-----------------" << endl; dt = (tend.QuadPart - tstart.QuadPart) / (double)nFreq.QuadPart; cout << "Total time :" << dt * 1000000 << "us" << endl;//dt } void main_thread_work() { // 让主线程持续运行,保持就绪状态,作为yield的切换目标 while (true) { volatile int x = 0; for (int i=0; i<1000; i++) x++; } } int main() { std::thread thread_2(thread_function_2); main_thread_work(); thread_2.join(); return 0; }
修改后,每次yield()都会触发线程切换,总耗时会明显上升,接近多次线程切换的时间总和。
内容的提问来源于stack exchange,提问作者minjiew
相关产品推荐
相关产品推荐

