c++11 yield函数的使用

本文介绍了C++11中新增的yield函数,该函数位于std::this_thread::yield命名空间中,用于使当前线程放弃执行权,从而提高CPU利用率。通过示例代码展示了如何在等待操作完成时合理使用yield来避免不必要的CPU占用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

yield函数时c++11的新特性,它在std::this_thread::yield命名空间中实现,函数声明如下:

void yield() noexcept; 

其作用是当前线程“放弃”执行,让操作系统调度另一线程继续执行

比如说你的线程需要等待某个操作完成,如果你直接用一个循环不断判断这个操作是否完成就会使得这个线程占满CPU时间,这会造成资源浪费。这时候你可以判断一次操作是否完成,如果没有完成就调用yield交出时间片,过一会儿再来判断是否完成,这样这个线程占用CPU时间会大大减少。,例如:

while(!isDone()); // Bad
while(!isDone()) yield(); // Good

代码示例:

#include "stdafx.h"
#include <iostream>  
#include <chrono>  
#include <thread> 
#include <atomic>
#include <mutex>

std::mutex g_mutex;
std::atomic<bool> ready(false);

void count1m(int id) 
{
    while (!ready)// wait until main() sets ready... 
    {             
        //若线程还有没创建的,将当前线程分配的cpu时间片,让调度器安排给其他线程,
        //由于使用了yield函数,在 not Ready 情况下,避免了空循环,在一定程度上,可以提高cpu的利用率
        std::this_thread::yield();
    }

    for ( int i = 0; i < 1000000; ++i) {}

    std::lock_guard<std::mutex> lock(g_mutex);
    std::cout << "thread : "<< id << std::endl;
}

int main()
{
    std::thread threads[10];

    std::cout << "race of 10 threads that count to 1 million:\n";

    for (int i = 0; i < 10; ++i)
    {
        threads[i] = std::thread(count1m, i);
    }

    ready = true;               // go!

    for (auto& th : threads)
    {
        th.join();
    }

    std::cout << '\n';

    return 0;
}

运行结果:
这里写图片描述

参考资料:
http://blog.youkuaiyun.com/tanningzhong/article/details/78248258
http://www.cplusplus.com/reference/thread/this_thread/yield/

<think>首先,用户的问题是关于C++中线程yield使用,具体是“C++ std::thread yield usage”。用户提到了“std::thread yield”,但在C++标准库中,yield函数是std::this_thread::yield(),而不是std::thread::yield()。所以,我需要纠正并解释正确的用法。 从系统级指令: - 所有行内数学表达式必须使用$...$格式。但在这个上下文中,可能没有数学表达式,主要是代码和解释。 - 独立公式用$$...$$,但可能不需要。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。用户提供了引用,但它们是参考,我需要检查是否相关。 用户提供的引用: - [^1]: 关于std::this_thread::yield(),提供提示让其他线程运行。 - [^2]: 关于std::is_constant_evaluated,不直接相关。 - [^3]: 关于协程和阻塞操作,提到std::this_thread::sleep_for,与yield相关。 - [^4]: 关于并发编程,线程管理。 用户的问题直接涉及std::this_thread::yield(),所以我应该基于[^1]和[^3]来回答。 回答结构: 1. 解释std::this_thread::yield()的作用。 2. 提供用法示例。 3. 讨论何时使用它。 4. 注意事项。 5. 生成相关问题。 确保回答真实可靠:yield()是用于提示调度器让出CPU,但它不是强制的;实际行为取决于操作系统调度器。 步骤: 1. 介绍yield()函数:它是std::this_thread命名空间中的函数。 2. 语法:void yield() noexcept; 3. 作用:让当前线程放弃其时间片,允许其他线程运行。 4. 使用场景:当线程在忙等待或循环中,为了避免浪费CPU资源。 5. 示例代码:使用C++代码展示。 6. 注意事项:不要过度使用,因为它可能导致性能问题;在协程中可能更高效。 7. 引用:在相关部分添加引用标识。 生成相关问题:在最后添加,如关于性能、替代方案等。 完整回答: - 开头解释yield()。 - 代码示例。 - 讨论。 - 相关问题。 用中文回答。</think>### C++ 中 std::this_thread::yield() 的使用C++ 并发编程中,`std::this_thread::yield()` 是一个重要的函数,用于提示当前线程主动让出 CPU 时间片,允许其他线程运行。它属于 `<thread>` 头文件中的 `std::this_thread` 命名空间,而不是 `std::thread` 类。yield 的主要目的是优化资源使用,避免忙等待(busy-waiting)导致的 CPU 浪费,这在多核处理器环境中尤其有用[^1]。 #### 基本语法和作用 - **语法**: `void std::this_thread::yield() noexcept;` - **作用**: 调用此函数时,当前线程会向操作系统调度器发出提示,自愿放弃剩余的时间片,使调度器有机会切换到其他就绪线程。这有助于减少不必要的上下文切换开销,并改善整体系统响应性[^1][^3]。 - **关键点**: - yield 是一个“提示”(hint),实际行为取决于操作系统调度器(如 Linux 的 CFS 或 Windows 的调度器),不保证立即切换线程。 - 它不会阻塞线程,而是使线程进入就绪状态,等待重新调度。 - 常用于忙等待循环中,例如等待某个条件变为真,避免空转消耗 CPU 资源。 #### 使用示例 以下是一个简单的 C++ 示例,演示 `yield()` 在忙等待中的应用。场景:一个线程等待另一个线程设置标志位,使用 yield 来减少 CPU 占用。 ```cpp #include <iostream> #include <thread> #include <atomic> #include <chrono> std::atomic<bool> flag(false); // 原子标志位 void worker_thread() { // 模拟耗时任务 std::this_thread::sleep_for(std::chrono::milliseconds(100)); flag.store(true); // 设置标志位 } void waiting_thread() { // 忙等待循环:使用 yield 避免高 CPU 占用 while (!flag.load()) { std::this_thread::yield(); // 让出 CPU,允许其他线程运行 } std::cout << "标志位已设置,继续执行!" << std::endl; } int main() { std::thread worker(worker_thread); std::thread waiter(waiting_thread); worker.join(); waiter.join(); return 0; } ``` **编译说明**: - 使用 C++11 或更高版本编译(例如:`g++ -std=c++11 -pthread example.cpp -o example`)。 - 需要链接 pthread 库(在 Linux/macOS 中)。 **代码解释**: - `worker_thread` 设置一个原子标志位 `flag` 为 true,模拟任务完成。 - `waiting_thread` 在循环中检查 `flag`。如果 `flag` 为 false,调用 `yield()` 让出 CPU,而不是空转。 - 这样,避免了忙等待的高 CPU 使用率(可能从 100% 降至接近 0%),同时减少了线程上下文切换的开销[^3]。 #### 适用场景和最佳实践 - **常见场景**: - 忙等待优化:如自旋锁(spinlock)或条件变量前的轻量级等待。 - 协程调度:在协程中,yield 可用于手动让出控制权,提升并发效率[^3]。 - 实时系统:在低延迟应用中,减少不必要的调度延迟。 - **最佳实践**: - **不要过度使用**: 频繁调用 yield 可能导致过多的上下文切换,反而降低性能(例如,在紧密循环中)。仅在等待条件时使用,并考虑结合 `std::this_thread::sleep_for` 添加短暂延迟。 - **替代方案**: 对于更复杂的同步,优先使用高级原语如 `std::condition_variable` 或 `std::mutex`,它们更高效且不易出错。 - **平台差异**: yield 的行为依赖于操作系统。在 Linux 中,它可能调用 `sched_yield()`;在 Windows 中,调用 `SwitchToThread()`。测试在不同系统下的表现。 - **注意事项**: - yield 不保证公平性:其他线程不一定获得执行机会。 - 在单核 CPU 上,yield 可能无效,因为只有一个线程能运行。 - C++20 引入了协程(coroutines),yield 在协程中可能被更高效的 `co_await` 取代[^3]。 总之,`std::this_thread::yield()` 是一个轻量级工具,用于优化线程协作。但它应谨慎使用,通常作为性能调优的最后手段。在多数情况下,高级同步机制更可靠[^1][^4]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值