You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 08:50:27