C++ Academy · 课时

条件变量与工作线程模式

使用 std::condition_variable 和经典的工作线程池模式协调线程

第 3 / 4 课14 个步骤

条件变量与工作线程模式 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

什么是条件变量

条件变量可以让线程等待,直到另一个线程发出条件已改变的信号。它用于协调生产者和消费者。

std::condition_variable 基础

条件变量与 std::mutex 和谓词配合使用。等待线程在等待期间释放锁,并在唤醒时重新获取锁。

#include <condition_variable>
#include <mutex>
#include <queue>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> tasks;
bool done = false;

等待条件

请使用 cv.wait(lock, predicate)。它会以原子方式解锁互斥量并进入休眠,直到收到通知。唤醒后,它会重新加锁并检查谓词;如果谓词为假,就会再次休眠。

std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });

通知

生产者线程更改状态后,会调用 cv.notify_one() 或 cv.notify_all()。更改状态期间应持有锁。

{
    std::lock_guard<std::mutex> lock(mtx);
    tasks.push(42);
}
cv.notify_one();

生产者-consumer 模式

经典示例:生产者推送任务;consumer 等待任务。

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !tasks.empty() || done; });
        if (done && tasks.empty()) break;
        int task = tasks.front();
        tasks.pop();
        lock.unlock();
        process(task);
    }
}

虚假唤醒

等待条件变量的线程可能在未收到通知的情况下被唤醒。因此,wait 接受一个谓词——每次唤醒时都会重新检查该谓词。

notify_one 与 notify_all

当一个等待者即可继续执行时,请使用 notify_one。当状态更改会影响所有等待者时,请使用 notify_all(例如发送关闭信号时)。

定时等待

wait_for(lock, duration) 和 wait_until(lock, time_point) 会在收到通知或 timeout 后唤醒。

if (cv.wait_for(lock, 1s, [] { return ready; })) {
    /* condition met */
} else {
    /* timed out */
}

工作线程池骨架

一种常见模式是:固定数量的工作线程从共享队列中取出任务。可使用互斥锁、条件变量、队列和原子停止标志来构建。

避免丢失唤醒

请始终在更改状态期间持有互斥锁,同时修改共享状态并调用 notify_*(在调用通知前刚好释放锁也可以,但请确保顺序正确)。否则,等待者可能会错过通知。

std::counting_semaphore(C++20)

对于简单的基于计数的信号传递,C++20 新增了 std::counting_semaphore;对于某些模式,它比条件变量更简单。

谨防死锁

等待条件变量时持有多个锁可能导致死锁。请以一致的顺序获取锁,并对多个互斥锁使用 std::scoped_lock。

快速检查

即使您只是想等待通知,cv.wait(lock, predicate) 为什么仍然需要一个谓词?

回顾

条件变量用于协调等待状态更改的线程。请使用 wait(lock, predicate) 处理虚假唤醒,在互斥锁保护下修改状态,然后调用 notify_one 或 notify_all。

免费开始

用 AI 导师学习 C++ — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
51
课程
203

常见问题解答

「条件变量与工作线程模式」课时是免费的吗?

是的 — 「条件变量与工作线程模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「条件变量与工作线程模式」这节课中我会学到什么?

使用 std::condition_variable 和经典的工作线程池模式协调线程 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「条件变量与工作线程模式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. std::thread:加入与分离
  2. std::mutex、lock_guard 与 unique_lock
  3. 条件变量与工作线程模式
  4. std::async 与 std::future 基础
← 返回 C++ Academy