c++ 的std::condition_variable

C++ 的 std::conditionvariable,从啥是它到怎么用,一步步讲明白。std::conditionvariable 是 C++11 引入的一个多线程同步工具,跟 std::mutex 搭配,能让线程“等条件”再干活,特别实用。

啥是 std::condition_variable?

想象你在饭店排队买饭,前台说:“饭还没好,等会儿。” 你就站那儿等着,有人喊“饭好了!”你才去拿。std::condition_variable 就像这个“喊话器”:

一个线程等着某个条件(比如“数据准备好”)。 另一个线程干完活,喊一声“好了”,等着的人就醒过来。 简单说:std::condition_variable 是线程间的一个“信号灯”,用来通知“条件满足了”。

为啥用它?

省资源:比忙等(一直循环检查)节约 CPU。

协作:线程间有条件地配合,比如生产者-消费者。

灵活:跟锁一起用,安全又方便。

怎么用? 得包含 ,因为它俩是搭档。

1. 基本用法

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false; // 条件

void worker() {
    std::unique_lock<std::mutex> lock(mtx); // 上锁
    cv.wait(lock, [] { return ready; });    // 等条件
    std::cout << "工人醒了,干活!\n";
}

void boss() {
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 假装忙1秒
    {
        std::lock_guard<std::mutex> lock(mtx); // 上锁
        ready = true;                          // 设置条件
    }
    cv.notify_one(); // 喊一声“好了”
}

int main() {
    std::thread t1(worker);
    std::thread t2(boss);
    t1.join();
    t2.join();
    return 0;
}

输出:

(等1秒)
工人醒了,干活!

std::condition_variable cv:信号灯对象。

cv.wait(lock, 条件):等着,直到条件为 true,期间解锁让别人干活。

cv.notify_one():喊醒一个等着的线程。

std::uniquelock:比 lockguard 灵活,能配合 wait。

2. 生产者-消费者

经典场景:一个线程生产数据,另一个消费:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

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

void producer() {
    for (int i = 1; i <= 3; i++) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        {
            std::lock_guard<std::mutex> lock(mtx);
            data_queue.push(i);
            std::cout << "生产: " << i << "\n";
        }
        cv.notify_one(); // 通知消费者
    }
    {
        std::lock_guard<std::mutex> lock(mtx);
        done = true; // 生产完了
    }
    cv.notify_one();
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !data_queue.empty() || done; }); // 等数据或结束
        if (!data_queue.empty()) {
            int data = data_queue.front();
            data_queue.pop();
            std::cout << "消费: " << data << "\n";
            lock.unlock(); // 手动解锁(可选)
        } else if (done) {
            break; // 数据空且生产完了,退出
        }
    }
    std::cout << "消费者下班\n";
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}

输出:

(等1秒)
生产: 1
消费: 1
(等1秒)
生产: 2
消费: 2
(等1秒)
生产: 3
消费: 3
消费者下班

wait(lock, 条件):等队列有东西或生产结束。 notify_one():每次生产完喊一声。 done:标记生产完成,避免消费者死等。

3. 加超时

不想一直等,可以加时间限制:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    if (cv.wait_for(lock, std::chrono::seconds(2), [] { return ready; })) {
        std::cout << "条件满足,干活\n";
    } else {
        std::cout << "超时了,不等了\n";
    }
}

void boss() {
    std::this_thread::sleep_for(std::chrono::seconds(3)); // 故意晚3秒
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
}

int main() {
    std::thread t1(worker);
    std::thread t2(boss);
    t1.join();
    t2.join();
    return 0;
}

输出:

(等2秒)
超时了,不等了
(再等1秒,boss才通知)

wait_for(lock, 时间, 条件):最多等 2 秒,返回 true(条件满足)或 false(超时)。

4. 通知所有线程

用 notify_all() 喊醒所有等着的线程:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return ready; });
    std::cout << "工人 " << id << " 醒了\n";
}

int main() {
    std::thread t1(worker, 1);
    std::thread t2(worker, 2);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_all(); // 喊醒所有
    t1.join();
    t2.join();
    return 0;
}

输出:

(等1秒)
工人 1 醒了
工人 2 醒了

notify_all():通知所有等着的人。

注意点

必须配锁: wait 需要 std::uniquelock,不能用 lockguard。

伪唤醒: 系统可能无故唤醒线程,所以用条件([] { return ready; })检查。

顺序: 先改条件,再 notify,否则可能错过信号。

性能: 比忙等好,但锁和等待多了也耗时。

需要掌握啥?

基本用法: wait(lock, 条件)、notify_one()。

和锁搭配: std::mutex 和 std::unique_lock。

高级用法: waitfor(超时)、notifyall(全通知)。

场景: 生产者-消费者、线程同步、条件等待。

调试: 注意条件和通知顺序,别漏信号。

总结

std::condition_variable 是线程间的“信号员”,等条件+通知。

用法:配 mutex,wait 等着,notify 喊醒。

适合协作式多线程,现代 C++ 必备。

文档信息

版权声明:可自由转载(请注明转载出处)-非商用-非衍生

发表时间:2025年7月1日 12:25