目录
更多,请看https://blog.youkuaiyun.com/keep_trying_go/category_12926769.html
std::this_thread::yield() 是 C++ 标准库中的一个函数,用于 主动让出当前线程的 CPU 时间片,允许操作系统调度其他线程运行。它通常用于 减少忙等待(busy-waiting)的 CPU 占用,特别是在自旋锁(spinlock)或无锁(lock-free)编程中。
1. yield() 的作用
-
让出 CPU:当前线程暂时放弃 CPU,让其他线程有机会运行。
-
避免忙等待:在循环中等待某个条件时(如自旋锁),用
yield()可以减少 CPU 资源的浪费。 -
不保证立即切换:
yield()只是一个提示(hint),具体是否切换线程由操作系统决定。
2. 使用场景
(1) 自旋锁(Spinlock)
在自旋锁中,如果锁被占用,线程通常会循环检查锁状态。如果直接 while 循环,会占用大量 CPU,而 yield() 可以让线程在等待时让出 CPU。
#include <atomic>
#include <thread>
std::atomic_flag lock = ATOMIC_FLAG_INIT;
void spinlock_acquire() {
while (lock.test_and_set(std::memory_order_acquire)) { // 尝试获取锁
std::this_thread::yield(); // 获取失败,让出 CPU
}
}
void spinlock_release() {
lock.clear(std::memory_order_release); // 释放锁
}
void worker() {
spinlock_acquire();
// 临界区(Critical Section)
spinlock_release();
}
(2) 无锁(Lock-Free)数据结构
在 CAS(Compare-And-Swap)操作失败时,可以用 yield() 减少 CPU 竞争。
std::atomic<int> counter(0);
void increment() {
int expected = counter.load();
while (!counter.compare_exchange_weak(expected, expected + 1)) {
std::this_thread::yield(); // CAS 失败,让出 CPU
}
}
(3) 避免忙等待
如果线程需要等待某个条件(如任务队列非空),可以用 yield() 代替空循环。
std::atomic<bool> ready(false);
void consumer() {
while (!ready.load()) {
std::this_thread::yield(); // 等待 ready 变为 true
}
// 执行任务
}
3. yield() vs sleep_for()
| 方法 | 作用 | 适用场景 |
|---|---|---|
yield() | 主动让出 CPU,但不保证休眠 | 自旋锁、无锁编程 |
sleep_for() | 强制休眠一段时间 | 定时任务、固定延迟 |
// 用 yield() 优化自旋锁
while (lock.test_and_set()) {
std::this_thread::yield(); // 让出 CPU,减少竞争
}
// 用 sleep_for() 控制固定延迟
while (lock.test_and_set()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // 固定休眠 1ms
}
4. 注意事项
-
yield()只是提示,不保证线程切换:-
操作系统可能忽略
yield(),特别是在单核 CPU 或高负载情况下。
-
-
不要滥用
yield():-
如果线程频繁
yield(),可能导致 上下文切换开销增加,反而降低性能。
-
-
适合短时间等待:
-
如果等待时间较长(如 I/O 操作),应该用
sleep_for或condition_variable。
-
1582

被折叠的 条评论
为什么被折叠?



