C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > c++ std::condition_variable使用

c++中std::condition_variable的使用及注意事项

作者:LumiTiger

本文深入讲解 std::condition_variable 在多线程同步中的核心作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、核心原理速览

二、入门级示例

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

#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:虚假唤醒演示与正确写法

错误写法(无谓词,可能因虚假唤醒导致逻辑错误)

#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;
}

正确写法(带谓词,自动处理虚假唤醒)

#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:多生产者-多消费者(有界队列)

#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_forvswait_until)

#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批量唤醒场景

#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:通用线程安全队列(双条件变量优化)

#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)

#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)

#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:简化版线程池

#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

// 编译错误!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:通知丢失

// 线程会永久阻塞,因为通知在 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

// 虽然不会死锁,但性能极差
#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 来同步两个线程,消费者线程会不断循环检查标志位:

#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;
}

问题:

条件变量的解决方案

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

#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() 函数的内部逻辑是原子操作:

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

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

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

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

核心使用场景

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

场景 2:线程池

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

场景 4:线程屏障(Barrier)

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

什么时候不用std::condition_variable?

场景代码补充

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

#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:简化版线程池

#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:一次性 事件通知

#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:可复用线程屏障

#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:写优先读写锁实现

#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;
}

到此这篇关于c++中std::condition_variable的使用及注意事项的文章就介绍到这了,更多相关c++ std::condition_variable使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文