MST

星途 面试题库

面试题:并发与同步:条件变量在多线程同步场景中的常规应用

假设有一个生产者 - 消费者模型,生产者线程生产数据并放入缓冲区,消费者线程从缓冲区取出数据进行处理。请描述如何使用条件变量来实现生产者和消费者之间的同步,包括条件变量的初始化、等待和通知操作,同时简单说明相关互斥锁的作用。
22.4万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试
  1. 条件变量初始化: 在C++中,使用<condition_variable>库。首先声明一个std::condition_variable对象,例如:
#include <condition_variable>
#include <mutex>
#include <queue>

std::condition_variable cv;
std::mutex mtx;
std::queue<int> buffer;
const int buffer_size = 5;
  1. 生产者线程
    • 生产者在往缓冲区放入数据前,先获取互斥锁。
    • 检查缓冲区是否已满,如果满了,则通过cv.wait等待条件变量。在等待过程中,互斥锁会被自动释放,当条件变量被通知时,互斥锁会被重新获取。
    • 当缓冲区有空间时,放入数据,然后通知消费者线程(cv.notify_one()cv.notify_all())。
void producer() {
    int data = 0;
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        while (buffer.size() == buffer_size) {
            cv.wait(lock);
        }
        buffer.push(data++);
        lock.unlock();
        cv.notify_one();
    }
}
  1. 消费者线程
    • 消费者在从缓冲区取出数据前,先获取互斥锁。
    • 检查缓冲区是否为空,如果空了,则通过cv.wait等待条件变量。同样,等待过程中互斥锁会被释放,通知时重新获取。
    • 当缓冲区有数据时,取出数据进行处理,然后通知生产者线程(cv.notify_one()cv.notify_all())。
void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        while (buffer.empty()) {
            cv.wait(lock);
        }
        int data = buffer.front();
        buffer.pop();
        lock.unlock();
        // 处理数据
        cv.notify_one();
    }
}
  1. 互斥锁的作用
    • 互斥锁用于保护共享资源(这里是缓冲区),防止多个线程同时访问缓冲区,避免数据竞争和不一致。
    • 条件变量的wait操作需要一个已锁定的互斥锁,在等待过程中,互斥锁会被自动释放,这样其他线程才有机会修改共享资源(如生产者往缓冲区放数据,消费者从缓冲区取数据)。当条件变量被通知时,wait函数重新获取互斥锁,确保后续对共享资源的操作是安全的。