MST

星途 面试题库

面试题:C++并发编程中的线程安全数据结构

设计一个线程安全的队列(queue)数据结构,使用C++标准库中的多线程相关工具(如mutex、condition_variable等)。要求实现入队(enqueue)和出队(dequeue)操作,并考虑如何处理队列满和队列空的情况。
48.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

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

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

    void enqueue(const T& item) {
        std::unique_lock<std::mutex> lock(mutex_);
        notFull_.wait(lock, [this] { return queue_.size() < capacity_; });
        queue_.push(item);
        lock.unlock();
        notEmpty_.notify_one();
    }

    bool dequeue(T& item) {
        std::unique_lock<std::mutex> lock(mutex_);
        if (!notEmpty_.wait_for(lock, std::chrono::seconds(1), [this] { return!queue_.empty(); })) {
            return false;
        }
        item = queue_.front();
        queue_.pop();
        lock.unlock();
        notFull_.notify_one();
        return true;
    }

private:
    std::queue<T> queue_;
    std::mutex mutex_;
    std::condition_variable notEmpty_;
    std::condition_variable notFull_;
    size_t capacity_;
};

你可以通过以下方式使用这个线程安全队列:

int main() {
    ThreadSafeQueue<int> tsQueue(5);

    std::thread producer([&tsQueue] {
        for (int i = 0; i < 10; ++i) {
            tsQueue.enqueue(i);
            std::cout << "Produced: " << i << std::endl;
        }
    });

    std::thread consumer([&tsQueue] {
        int item;
        while (true) {
            if (tsQueue.dequeue(item)) {
                std::cout << "Consumed: " << item << std::endl;
            } else {
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        }
    });

    producer.join();
    consumer.join();

    return 0;
}

在这个实现中:

  1. ThreadSafeQueue类使用std::mutex来保护队列操作。
  2. std::condition_variable notEmpty_notFull_分别用于处理队列空和队列满的情况。
  3. enqueue方法在队列满时等待notFull_条件变量,直到队列有空间,然后将元素入队,并通知notEmpty_
  4. dequeue方法在队列空时等待notEmpty_条件变量,直到队列有元素,然后将元素出队,并通知notFull_。同时,dequeue方法使用wait_for设置了等待超时,如果超时则返回false