MST

星途 面试题库

面试题:C++多线程条件变量的应用

假设你正在开发一个生产者 - 消费者模型,生产者线程不断向一个队列中添加数据,消费者线程从队列中取出数据进行处理。请使用C++的条件变量(condition variable)和互斥锁实现该模型,并解释条件变量在其中起到的作用以及为什么要使用它。
43.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

std::queue<int> dataQueue;
std::mutex queueMutex;
std::condition_variable dataAvailable;
bool finished = false;

void producer() {
    for (int i = 0; i < 10; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::unique_lock<std::mutex> lock(queueMutex);
        dataQueue.push(i);
        std::cout << "Produced: " << i << std::endl;
        lock.unlock();
        dataAvailable.notify_one();
    }
    std::unique_lock<std::mutex> lock(queueMutex);
    finished = true;
    lock.unlock();
    dataAvailable.notify_all();
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(queueMutex);
        dataAvailable.wait(lock, [] { return!dataQueue.empty() || finished; });
        if (dataQueue.empty() && finished) {
            break;
        }
        int data = dataQueue.front();
        dataQueue.pop();
        std::cout << "Consumed: " << data << std::endl;
        lock.unlock();
    }
}

条件变量的作用及使用原因

  1. 作用:条件变量dataAvailable用于线程间的同步。生产者线程在向队列中添加数据后,通过dataAvailable.notify_one()dataAvailable.notify_all()通知等待在条件变量上的消费者线程,队列中有新数据可以处理了。消费者线程在从队列取数据前,通过dataAvailable.wait(lock, [] { return!dataQueue.empty() || finished; })等待条件变量被通知,并且在被唤醒后检查队列是否有数据(或是否生产者已完成生产),避免虚假唤醒。
  2. 使用原因:如果不使用条件变量,消费者线程需要不断地轮询队列是否有数据,这会浪费大量CPU资源。条件变量提供了一种线程等待特定条件满足的机制,线程在等待时会被阻塞挂起,不占用CPU资源,直到条件变量被通知,这样可以显著提高程序的效率,同时保证线程间的正确同步。

你可以通过以下方式测试这两个函数:

int main() {
    std::thread producerThread(producer);
    std::thread consumerThread(consumer);

    producerThread.join();
    consumerThread.join();

    return 0;
}