1.生产者-消费者模型

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

std::mutex mtx;
std::condition_variable cv_producer, cv_consumer;
std::queue<int> buffer;

const int MAX_BUFFER_SIZE = 5;

void producer() {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv_consumer.wait(lock, [] { return buffer.size() < MAX_BUFFER_SIZE; });//满足 cv_consumer唤醒不阻塞 往下执行 锁定

        // 生产者向缓冲区添加数据
        buffer.push(i);
        std::cout << "Produced: " << i << std::endl;

        lock.unlock();
        cv_producer.notify_one();  // 唤醒等待在生产者条件变量上的线程
    }
}

void consumer() {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv_producer.wait(lock, [] { return !buffer.empty(); });

        // 消费者从缓冲区取走数据
        int data = buffer.front();
        buffer.pop();
        std::cout << "Consumed: " << data << std::endl;

        lock.unlock();
        cv_consumer.notify_one();  // 唤醒等待在消费者条件变量上的线程
    }
}

int main() {
    std::thread producer_thread(producer);
    std::thread consumer_thread(consumer);

    producer_thread.join();
    consumer_thread.join();

    return 0;
}
cv_consumer.wait(lock, [] { return buffer.size() < MAX_BUFFER_SIZE; });

解释如下:

  • cv_consumer.wait(lock, predicate) 是一个等待函数,它会阻塞当前线程,直到被通知(通过 notify_onenotify_all)或超时,或者通过 predicate 判断为真。

  • lock 是一个 std::unique_lock 对象,用于锁定互斥量。在 wait 调用期间,互斥量会被释放,以允许其他线程访问被保护的共享资源。

  • predicate 是一个用于判断是否满足条件的函数。在这里,lambda 表达式 [] { return buffer.size() < MAX_BUFFER_SIZE; } 用于定义一个判断条件:缓冲区的大小是否小于最大缓冲区大小 MAX_BUFFER_SIZE

所以,cv_consumer.wait 会等待直到条件 buffer.size() < MAX_BUFFER_SIZE 为真,即缓冲区不满时才唤醒。一旦被唤醒,它会重新锁定互斥量,允许线程继续执行后续的操作。

在生产者-消费者问题中,这样的设计可以确保生产者在缓冲区不满时执行生产操作,而消费者在缓冲区非空时执行消费操作,从而实现线程的同步。

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

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

void producer() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟生产过程
    {
        std::lock_guard<std::mutex> lock(mtx);
        condition = true;
    }
    cv.notify_one(); // 通知消费者线程条件已满足
}

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return condition; }); // 等待条件变量满足
    std::cout << "Consumer: Received signal, consuming resources." << std::endl;
}

int main() {
    std::thread producer_thread(producer);
    std::thread consumer_thread(consumer);

    producer_thread.join();
    consumer_thread.join();

    return 0;
}

std::lock_guard:

std::lock_guard 是一种简单的锁管理器,它在构造时立即锁定互斥锁,并在析构时自动释放锁。由于其自动化的特性,适用于那些只需要在作用域内锁定和解锁的情况。
在生产者线程的上下文中,当需要在一段代码块内保护共享资源时,使用 std::lock_guard 是简单而直接的选择。
std::unique_lock:

std::unique_lock 提供了更大的灵活性,它允许延迟锁定和解锁,并且可以手动控制锁定和解锁的时机。这使得 std::unique_lock 更适合一些需要更复杂锁定策略的场景,例如条件变量的使用。
在消费者线程的上下文中,当需要等待条件变量的发生时,使用 std::unique_lock 是更合适的选择,因为它可以方便地与条件变量配合使用,并提供了更灵活的锁定和解锁操作。

cv.wait(lock, []{ return condition; });:这行代码调用了条件变量 cv 的 wait 方法,它需要两个参数。第一个参数是 lock,它是一个 std::unique_lock<std::mutex> 对象,用于锁定互斥锁。第二个参数是一个可调用对象(通常是 Lambda 表达式),用于检查条件是否满足。

[]{ return condition; }:这是一个 Lambda 表达式,它用于检查条件是否满足。Lambda 表达式返回一个 bool 类型的值,表示条件是否满足。在这个例子中,Lambda 表达式返回 condition 的值,即检查条件变量 condition 是否为 true。

cv.wait(lock, []{ return condition; });:这行代码的作用是:如果条件 condition 不满足(即返回 false),则当前线程会被阻塞,同时释放 lock 对象所锁定的互斥锁。当其他线程修改了条件变量 condition 的值并调用了 cv.notify_one() 或 cv.notify_all() 时,当前线程会被唤醒,并尝试重新获取 lock 对象所锁定的互斥锁。如果条件 condition 满足(即返回 true),则当前线程不会被阻塞,继续执行后续代码。

总之,这段代码的作用是让当前线程在条件变量 condition 满足之前等待,并释放互斥锁以允许其他线程修改共享状态。

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值