std::condition_variable的使用及主要事项

std::condition_variable

一、核心原理速览

  • 本质:线程同步原语,实现阻塞-通知机制,避免忙等待
  • 强制要求:必须与 std::unique_lock<std::mutex> 配合使用(wait 需要原子解锁/加锁)
  • 核心函数:
    • wait(lock):阻塞直到被通知(存在虚假唤醒)
    • wait(lock, pred):阻塞直到被通知且 pred()true(推荐,自动处理虚假唤醒)
    • notify_one():唤醒一个等待线程
    • notify_all():唤醒所有等待线程
    • wait_for()/wait_until():带超时的等待

二、入门级示例

示例1:最基础单生产者-单消费者

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
int data = 0;
bool ready = false;

void producer() {
    std::lock_guard<std::mutex> lock(mtx);
    data = 42;
    ready = true;
    cv.notify_one();
}

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });
    std::cout << "Received: " << data << std::endl;
}

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

核心知识点:条件变量最基本的通知-等待流程,生产者修改共享状态后通知消费者。


示例2:虚假唤醒演示与正确写法

错误写法(无谓词,可能因虚假唤醒导致逻辑错误)
cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

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

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock);
    std::cout << "Worker running" << std::endl;
}

int main() {
    std::thread t(worker);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    t.join();
    return 0;
}
正确写法(带谓词,自动处理虚假唤醒)
cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

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 << "Worker running" << std::endl;
}

int main() {
    std::thread t(worker);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
    t.join();
    return 0;
}

核心知识点:虚假唤醒是操作系统的正常行为,必须通过谓词或循环检查条件来规避。


三、进阶级示例

示例3:多生产者-多消费者(有界队列)

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <chrono>

std::mutex mtx;
std::condition_variable cv;
std::queue<int> q;
const int MAX_SIZE = 3;

void producer(int id) {
    for (int i = 0; i < 5; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, []{ return q.size() < MAX_SIZE; });
        q.push(i);
        std::cout << "Producer " << id << " produced " << i << std::endl;
        lock.unlock();
        cv.notify_all();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void consumer(int id) {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        if (cv.wait_for(lock, std::chrono::seconds(2), []{ return!q.empty(); })) {
            int val = q.front();
            q.pop();
            std::cout << "Consumer " << id << " consumed " << val << std::endl;
            lock.unlock();
            cv.notify_all();
            if (val == 4) break;
        } else {
            std::cout << "Consumer " << id << " timeout" << std::endl;
            break;
        }
    }
}

int main() {
    std::thread p1(producer, 1);
    std::thread p2(producer, 2);
    std::thread c1(consumer, 1);
    std::thread c2(consumer, 2);
    p1.join();
    p2.join();
    c1.join();
    c2.join();
    return 0;
}

核心知识点 :处理多线程竞争下的队列满/空状态,使用 notify_all 唤醒所有等待线程,wait_for 避免永久阻塞。


示例4:超时等待(wait_for vs wait_until

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

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

void worker1() {
    std::unique_lock<std::mutex> lock(mtx);
    if (cv.wait_for(lock, std::chrono::seconds(2), []{ return ready; })) {
        std::cout << "Worker1: Ready" << std::endl;
    } else {
        std::cout << "Worker1: Timeout" << std::endl;
    }
}

void worker2() {
    std::unique_lock<std::mutex> lock(mtx);
    auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(3);
    if (cv.wait_until(lock, deadline, []{ return ready; })) {
        std::cout << "Worker2: Ready" << std::endl;
    } else {
        std::cout << "Worker2: Timeout" << std::endl;
    }
}

int main() {
    std::thread t1(worker1);
    std::thread t2(worker2);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_all();
    t1.join();
    t2.join();
    return 0;
}

核心知识点wait_for 等待相对时间,wait_until 等待绝对时间点,两者都支持谓词参数。


示例5:notify_all 批量唤醒场景

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>

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

void worker(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return start; });
    std::cout << "Worker " << id << " started" << std::endl;
}

int main() {
    std::vector<std::thread> workers;
    for (int i = 0; i < 5; ++i) {
        workers.emplace_back(worker, i);
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Main: Starting all workers" << std::endl;
    {
        std::lock_guard<std::mutex> lock(mtx);
        start = true;
    }
    cv.notify_all();
    for (auto& t : workers) {
        t.join();
    }
    return 0;
}

核心知识点 :当多个线程需要等待同一个全局信号时,必须使用 notify_all,否则只会唤醒一个线程。


四、精通级示例

示例6:通用线程安全队列(双条件变量优化)

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>

template <typename T>
class ThreadSafeQueue {
public:
    explicit ThreadSafeQueue(size_t max_size) : max_size_(max_size) {}

    void push(T item) {
        std::unique_lock<std::mutex> lock(mutex_);
        not_full_.wait(lock, [this]{ return queue_.size() < max_size_; });
        queue_.push(std::move(item));
        not_empty_.notify_one();
    }

    T pop() {
        std::unique_lock<std::mutex> lock(mutex_);
        not_empty_.wait(lock, [this]{ return!queue_.empty(); });
        T item = std::move(queue_.front());
        queue_.pop();
        not_full_.notify_one();
        return item;
    }

    size_t size() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return queue_.size();
    }

    bool empty() const {
        std::lock_guard<std::mutex> lock(mutex_);
        return queue_.empty();
    }

private:
    std::queue<T> queue_;
    mutable std::mutex mutex_;
    std::condition_variable not_empty_;
    std::condition_variable not_full_;
    size_t max_size_;
};

void producer(ThreadSafeQueue<int>& q, int id) {
    for (int i = 0; i < 5; ++i) {
        q.push(i);
        std::cout << "Producer " << id << " pushed " << i << std::endl;
    }
}

void consumer(ThreadSafeQueue<int>& q, int id) {
    for (int i = 0; i < 5; ++i) {
        int val = q.pop();
        std::cout << "Consumer " << id << " popped " << val << std::endl;
    }
}

int main() {
    ThreadSafeQueue<int> q(3);
    std::thread p1(producer, std::ref(q), 1);
    std::thread p2(producer, std::ref(q), 2);
    std::thread c1(consumer, std::ref(q), 1);
    std::thread c2(consumer, std::ref(q), 2);
    p1.join();
    p2.join();
    c1.join();
    c2.join();
    return 0;
}

核心知识点 :使用两个独立条件变量分别控制队列非空和非满,避免 notify_all 带来的惊群效应,大幅提升多线程场景下的性能。


示例7:一次性事件(One-shot Event)

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>

class OneShotEvent {
public:
    void signal() {
        std::lock_guard<std::mutex> lock(mtx_);
        signaled_ = true;
        cv_.notify_all();
    }

    void wait() {
        std::unique_lock<std::mutex> lock(mtx_);
        cv_.wait(lock, [this]{ return signaled_; });
    }

private:
    std::mutex mtx_;
    std::condition_variable cv_;
    bool signaled_ = false;
};

void worker(OneShotEvent& event, int id) {
    std::cout << "Worker " << id << " waiting for signal" << std::endl;
    event.wait();
    std::cout << "Worker " << id << " received signal" << std::endl;
}

int main() {
    OneShotEvent event;
    std::vector<std::thread> workers;
    for (int i = 0; i < 3; ++i) {
        workers.emplace_back(worker, std::ref(event), i);
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Main: Sending signal" << std::endl;
    event.signal();
    for (auto& t : workers) {
        t.join();
    }
    return 0;
}

核心知识点 :实现一次性通知机制,条件一旦满足就永远为true,后续调用 wait 会立即返回,适合初始化完成、程序启动信号等场景。


示例8:线程屏障(Barrier)

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>

class Barrier {
public:
    explicit Barrier(size_t count) : count_(count), waiting_(0), generation_(0) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mtx_);
        size_t gen = generation_;
        if (++waiting_ == count_) {
            waiting_ = 0;
            generation_++;
            cv_.notify_all();
        } else {
            cv_.wait(lock, [this, gen]{ return gen!= generation_; });
        }
    }

private:
    std::mutex mtx_;
    std::condition_variable cv_;
    size_t count_;
    size_t waiting_;
    size_t generation_;
};

void worker(Barrier& barrier, int id) {
    std::cout << "Worker " << id << " phase 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    barrier.wait();
    std::cout << "Worker " << id << " phase 2" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    barrier.wait();
    std::cout << "Worker " << id << " done" << std::endl;
}

int main() {
    Barrier barrier(3);
    std::vector<std::thread> workers;
    for (int i = 0; i < 3; ++i) {
        workers.emplace_back(worker, std::ref(barrier), i);
    }
    for (auto& t : workers) {
        t.join();
    }
    return 0;
}

核心知识点 :实现多线程同步点,所有线程必须到达屏障后才能继续执行。通过 generation 计数器支持多次屏障同步。


示例9:简化版线程池

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <functional>

class ThreadPool {
public:
    explicit ThreadPool(size_t num_threads) : stop_(false) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers_.emplace_back([this]{
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(mtx_);
                        cv_.wait(lock, [this]{ return stop_ ||!tasks_.empty(); });
                        if (stop_ && tasks_.empty()) {
                            return;
                        }
                        task = std::move(tasks_.front());
                        tasks_.pop();
                    }
                    task();
                }
            });
        }
    }

    void submit(std::function<void()> task) {
        {
            std::lock_guard<std::mutex> lock(mtx_);
            tasks_.push(std::move(task));
        }
        cv_.notify_one();
    }

    ~ThreadPool() {
        {
            std::lock_guard<std::mutex> lock(mtx_);
            stop_ = true;
        }
        cv_.notify_all();
        for (auto& t : workers_) {
            t.join();
        }
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> tasks_;
    std::mutex mtx_;
    std::condition_variable cv_;
    bool stop_;
};

int main() {
    ThreadPool pool(4);
    for (int i = 0; i < 10; ++i) {
        pool.submit([i]{
            std::cout << "Task " << i << " executed by thread " << std::this_thread::get_id() << std::endl;
        });
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 0;
}

核心知识点:条件变量是线程池的核心同步机制,工作线程等待任务队列非空,主线程提交任务后唤醒一个工作线程执行。


五、常见陷阱与反例

反例1:使用 std::lock_guard 代替 std::unique_lock

cpp 复制代码
// 编译错误!lock_guard 不支持解锁/重新加锁
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

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

void worker() {
    std::lock_guard<std::mutex> lock(mtx);
    cv.wait(lock);
}

int main() {
    std::thread t(worker);
    t.join();
    return 0;
}

反例2:通知丢失

cpp 复制代码
// 线程会永久阻塞,因为通知在 wait 之前发送
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

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

void worker() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock);
}

int main() {
    std::thread t(worker);
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
    t.join();
    return 0;
}

解决方法 :始终使用带谓词的 wait,它会在阻塞前先检查条件。

反例3:持有锁时调用 notify

cpp 复制代码
// 虽然不会死锁,但性能极差
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

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 << "Worker running" << std::endl;
}

int main() {
    std::thread t(worker);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock(mtx);
    ready = true;
    cv.notify_one(); // 持有锁时通知,被唤醒的线程会立即阻塞
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 0;
}

解决方法 :先解锁互斥量,再调用 notify


六、实践总结

  1. 永远使用带谓词的 wait,这是避免虚假唤醒和通知丢失的唯一可靠方法
  2. 必须使用 std::unique_lock 与条件变量配合
  3. 先解锁再通知,避免被唤醒的线程立即阻塞在锁上
  4. 优先使用 notify_one 而非 notify_all,减少惊群效应
  5. 避免在临界区执行耗时操作,缩小锁的粒度
  6. 使用双条件变量 优化生产者-消费者模型的性能

为什么要用 std::condition_variable

std::condition_variable 是 C++ 中用于线程高效协作的同步原语,核心价值是解决两个关键问题:


一、避免「忙等待(Busy Waiting)」,节省 CPU 资源

反例:纯轮询(忙等待)的糟糕性能

假设我们用一个全局标志位 ready 来同步两个线程,消费者线程会不断循环检查标志位:

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::mutex mtx;
bool ready = false;

void consumer() {
    while (true) {
        std::lock_guard<std::mutex> lock(mtx);
        if (ready) {
            std::cout << "Data received!" << std::endl;
            break;
        }
        // 即使加了 sleep,仍会浪费 CPU 时间片,且响应延迟
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

void producer() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock(mtx);
    ready = true;
}

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

问题

  • 消费者线程即使在 sleep,仍会周期性唤醒并占用 CPU 检查条件。
  • sleep 时间太长,会导致响应延迟;若太短,CPU 浪费更严重。

条件变量的解决方案

std::condition_variable 让线程真正休眠,直到被其他线程显式唤醒,完全不占用 CPU 时间片:

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

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

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 线程在此休眠,不占用 CPU
    std::cout << "Data received!" << std::endl;
}

void producer() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one(); // 显式唤醒消费者
}

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

优势

  • 消费者线程在 wait() 时会自动解锁互斥锁并进入阻塞状态,CPU 完全释放给其他线程。
  • 生产者线程 notify_one() 后,消费者线程被唤醒、重新加锁并检查条件,响应即时且无 CPU 浪费。

二、实现「原子性的解锁-等待-加锁」,避免竞态条件

wait() 函数的内部逻辑是原子操作

  1. 解锁互斥锁(让其他线程能修改共享状态)。
  2. 阻塞当前线程,等待通知。
  3. 被唤醒后,重新加锁并检查条件(避免虚假唤醒)。

如果没有这个原子性,可能会出现「通知丢失」的致命问题:

假设线程 A 先检查条件(不满足),然后准备休眠;但在它真正休眠前,线程 B 修改了条件并发送了通知------此时线程 A 还没开始等待,通知就丢失了,线程 A 会永久阻塞。

std::condition_variable 的原子性 wait() 完美解决了这个问题。


核心使用场景

场景 1:生产者-消费者模型(最经典)

  • 需求:一个/多个线程生产数据放入队列,一个/多个线程从队列取数据处理。
  • 条件变量的作用
    • 队列空时,消费者线程休眠,等待生产者放入数据。
    • 队列满时,生产者线程休眠,等待消费者取出数据。
  • 典型应用:日志系统(生产者写日志,消费者落盘)、视频流处理(生产者推流,消费者解码)。

场景 2:线程池

  • 需求:固定数量的工作线程等待任务队列,有任务时执行,无任务时休眠。
  • 条件变量的作用
    • 任务队列为空时,所有工作线程休眠。
    • 主线程提交任务后,唤醒一个工作线程执行。
  • 典型应用:Web 服务器处理并发请求、后台任务调度系统。

场景 3:一次性事件通知(One-shot Event)

  • 需求:某个全局事件(如系统初始化完成、资源加载完成)发生后,通知所有等待的线程开始工作。
  • 条件变量的作用
    • 事件未发生时,所有工作线程休眠。
    • 事件发生后,通过 notify_all() 批量唤醒所有线程。
  • 典型应用:游戏引擎的「资源加载完成后开始渲染」、分布式系统的「所有节点就绪后启动任务」。

场景 4:线程屏障(Barrier)

  • 需求:多个线程分阶段执行任务,所有线程必须到达某个「同步点」后,才能一起进入下一个阶段。
  • 条件变量的作用
    • 未到达同步点的线程休眠。
    • 最后一个线程到达后,唤醒所有线程继续执行。
  • 典型应用:并行计算(如矩阵乘法分块处理,所有块计算完后合并结果)、压力测试(所有虚拟用户准备好后同时发起请求)。

场景 5:读写锁的实现(进阶)

  • 需求:多个线程可以同时读共享数据,但写操作必须独占,且写操作优先级高于读操作。
  • 条件变量的作用
    • 有写线程等待时,新的读线程休眠,等待写线程完成。
    • 写线程完成后,唤醒所有等待的读线程或下一个写线程。

什么时候不用 std::condition_variable

  • 简单的互斥访问 :仅需保护共享数据不被并发修改,用 std::mutex 即可。
  • 一次性任务返回结果 :用 std::future/std::promise 更简洁,无需手动管理条件变量和标志位。
  • 周期性任务调度 :用定时器库(如 std::chrono + 线程 sleep)更合适。

场景代码补充


场景1:生产者-消费者模型(双条件变量优化)

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>

template <typename T>
class BoundedQueue {
public:
    explicit BoundedQueue(size_t capacity) : capacity_(capacity) {}

    void push(T item) {
        std::unique_lock<std::mutex> lock(mtx_);
        not_full_.wait(lock, [this]{ return queue_.size() < capacity_; });
        queue_.push(std::move(item));
        not_empty_.notify_one();
    }

    T pop() {
        std::unique_lock<std::mutex> lock(mtx_);
        not_empty_.wait(lock, [this]{ return!queue_.empty(); });
        T item = std::move(queue_.front());
        queue_.pop();
        not_full_.notify_one();
        return item;
    }

    size_t size() const {
        std::lock_guard<std::mutex> lock(mtx_);
        return queue_.size();
    }

private:
    std::queue<T> queue_;
    mutable std::mutex mtx_;
    std::condition_variable not_empty_;
    std::condition_variable not_full_;
    size_t capacity_;
};

void producer(BoundedQueue<int>& q, int id) {
    for (int i = 0; i < 5; ++i) {
        q.push(i);
        std::cout << "Producer " << id << " produced: " << i << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
}

void consumer(BoundedQueue<int>& q, int id) {
    for (int i = 0; i < 5; ++i) {
        int val = q.pop();
        std::cout << "Consumer " << id << " consumed: " << val << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main() {
    BoundedQueue<int> q(3);
    std::vector<std::thread> producers;
    std::vector<std::thread> consumers;

    for (int i = 0; i < 2; ++i) {
        producers.emplace_back(producer, std::ref(q), i);
    }
    for (int i = 0; i < 2; ++i) {
        consumers.emplace_back(consumer, std::ref(q), i);
    }

    for (auto& t : producers) t.join();
    for (auto& t : consumers) t.join();

    return 0;
}

场景2:简化版线程池

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include <functional>
#include <chrono>

class ThreadPool {
public:
    explicit ThreadPool(size_t num_threads) : stop_(false) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers_.emplace_back([this]{
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(mtx_);
                        cv_.wait(lock, [this]{ return stop_ ||!tasks_.empty(); });
                        if (stop_ && tasks_.empty()) return;
                        task = std::move(tasks_.front());
                        tasks_.pop();
                    }
                    task();
                }
            });
        }
    }

    void submit(std::function<void()> task) {
        {
            std::lock_guard<std::mutex> lock(mtx_);
            tasks_.push(std::move(task));
        }
        cv_.notify_one();
    }

    ~ThreadPool() {
        {
            std::lock_guard<std::mutex> lock(mtx_);
            stop_ = true;
        }
        cv_.notify_all();
        for (auto& t : workers_) t.join();
    }

private:
    std::vector<std::thread> workers_;
    std::queue<std::function<void()>> tasks_;
    std::mutex mtx_;
    std::condition_variable cv_;
    bool stop_;
};

int main() {
    ThreadPool pool(4);
    for (int i = 0; i < 10; ++i) {
        pool.submit([i]{
            std::cout << "Task " << i << " running on thread " 
                      << std::this_thread::get_id() << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        });
    }
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return 0;
}

场景3:一次性事件通知

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>

class OneShotEvent {
public:
    void signal() {
        std::lock_guard<std::mutex> lock(mtx_);
        signaled_ = true;
        cv_.notify_all();
    }

    void wait() {
        std::unique_lock<std::mutex> lock(mtx_);
        cv_.wait(lock, [this]{ return signaled_; });
    }

private:
    std::mutex mtx_;
    std::condition_variable cv_;
    bool signaled_ = false;
};

void worker(OneShotEvent& event, int id) {
    std::cout << "Worker " << id << " waiting for start signal..." << std::endl;
    event.wait();
    std::cout << "Worker " << id << " started working!" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    std::cout << "Worker " << id << " finished!" << std::endl;
}

int main() {
    OneShotEvent start_event;
    std::vector<std::thread> workers;

    for (int i = 0; i < 5; ++i) {
        workers.emplace_back(worker, std::ref(start_event), i);
    }

    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "\nMain thread sending start signal!\n" << std::endl;
    start_event.signal();

    for (auto& t : workers) t.join();

    return 0;
}

场景4:可复用线程屏障

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>

class Barrier {
public:
    explicit Barrier(size_t count) : count_(count), waiting_(0), generation_(0) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mtx_);
        size_t gen = generation_;
        if (++waiting_ == count_) {
            waiting_ = 0;
            generation_++;
            cv_.notify_all();
        } else {
            cv_.wait(lock, [this, gen]{ return gen!= generation_; });
        }
    }

private:
    std::mutex mtx_;
    std::condition_variable cv_;
    size_t count_;
    size_t waiting_;
    size_t generation_;
};

void worker(Barrier& barrier, int id) {
    std::cout << "Worker " << id << " entering phase 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    barrier.wait();
    std::cout << "Worker " << id << " entering phase 2" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    barrier.wait();
    std::cout << "Worker " << id << " completed all phases" << std::endl;
}

int main() {
    Barrier barrier(3);
    std::vector<std::thread> workers;

    for (int i = 0; i < 3; ++i) {
        workers.emplace_back(worker, std::ref(barrier), i);
    }

    for (auto& t : workers) t.join();

    return 0;
}

场景5:写优先读写锁实现

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>

class ReadWriteLock {
public:
    void lock_read() {
        std::unique_lock<std::mutex> lock(mtx_);
        read_cv_.wait(lock, [this]{ return write_waiting_ == 0 &&!writing_; });
        readers_++;
    }

    void unlock_read() {
        std::lock_guard<std::mutex> lock(mtx_);
        readers_--;
        if (readers_ == 0 && write_waiting_ > 0) {
            write_cv_.notify_one();
        }
    }

    void lock_write() {
        std::unique_lock<std::mutex> lock(mtx_);
        write_waiting_++;
        write_cv_.wait(lock, [this]{ return readers_ == 0 &&!writing_; });
        write_waiting_--;
        writing_ = true;
    }

    void unlock_write() {
        std::lock_guard<std::mutex> lock(mtx_);
        writing_ = false;
        if (write_waiting_ > 0) {
            write_cv_.notify_one();
        } else {
            read_cv_.notify_all();
        }
    }

private:
    std::mutex mtx_;
    std::condition_variable read_cv_;
    std::condition_variable write_cv_;
    int readers_ = 0;
    int write_waiting_ = 0;
    bool writing_ = false;
};

ReadWriteLock rw_lock;
int shared_data = 0;

void reader(int id) {
    for (int i = 0; i < 3; ++i) {
        rw_lock.lock_read();
        std::cout << "Reader " << id << " read: " << shared_data << std::endl;
        rw_lock.unlock_read();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void writer(int id) {
    for (int i = 0; i < 2; ++i) {
        rw_lock.lock_write();
        shared_data++;
        std::cout << "Writer " << id << " wrote: " << shared_data << std::endl;
        rw_lock.unlock_write();
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
}

int main() {
    std::vector<std::thread> readers;
    std::vector<std::thread> writers;

    for (int i = 0; i < 5; ++i) {
        readers.emplace_back(reader, i);
    }
    for (int i = 0; i < 2; ++i) {
        writers.emplace_back(writer, i);
    }

    for (auto& t : readers) t.join();
    for (auto& t : writers) t.join();

    return 0;
}
相关推荐
小菜鸡桃蛋狗1 小时前
C++——list
开发语言·c++
handler011 小时前
Git 核心指令速查
linux·c语言·c++·笔记·git·学习
fish_xk1 小时前
c++中的多态
c++
汉克老师1 小时前
GESP2025年6月认证C++五级( 第三部分编程题(1、奖品兑换))
c++·二分算法·gesp5级·gesp五级
hopetomorrow1 小时前
学习路之PHP --PHP 常用扩展及作用表
开发语言·学习·php
Lhan.zzZ1 小时前
笔记_2026.4.28_003
c++·笔记·qt·opencv
simple-L61 小时前
Java开发痛点技术文章大纲
java·开发语言
stolentime2 小时前
我常常追忆过去
c++·里程碑纪念
m0_635647482 小时前
Qt打包含有第三方库的软件为应用程序——CQtDeployer
开发语言·数据库·qt