乐闻世界logo
搜索文章和话题

C ++11 thread-safe queue

4 个月前提问
3 个月前修改
浏览次数34

1个答案

1

问题:请设计一个C++11的线程安全队列,并解释其原理。

回答:

实现一个线程安全队列主要涉及到对队列基本操作(如入队和出队)的同步处理。在C++11中,可以使用<mutex>, <condition_variable>以及<thread>等标准库来实现。

以下是一个简单的线程安全队列的设计:

cpp
#include <queue> #include <mutex> #include <condition_variable> template<typename T> class ThreadSafeQueue { private: mutable std::mutex mtx; // 互斥锁,mutable允许在const成员函数中被修改 std::queue<T> data_queue; // 标准库队列,用于存储数据 std::condition_variable data_cond; // 条件变量,用于同步 public: ThreadSafeQueue() {} // 禁止拷贝构造函数和拷贝赋值操作 ThreadSafeQueue(const ThreadSafeQueue& other) = delete; ThreadSafeQueue& operator=(const ThreadSafeQueue& other) = delete; // 入队操作 void push(T new_value) { std::lock_guard<std::mutex> lock(mtx); // 上锁 data_queue.push(std::move(new_value)); data_cond.notify_one(); // 通知一个等待线程(如果有的话) } // 出队操作 bool try_pop(T& value) { std::lock_guard<std::mutex> lock(mtx); if (data_queue.empty()) { return false; } value = std::move(data_queue.front()); data_queue.pop(); return true; } // 对于需要等待的出队操作 void wait_and_pop(T& value) { std::unique_lock<std::mutex> lock(mtx); data_cond.wait(lock, [this]{ return !data_queue.empty(); }); // 等待条件变量 value = std::move(data_queue.front()); data_queue.pop(); } // 判断队列是否为空 bool empty() const { std::lock_guard<std::mutex> lock(mtx); return data_queue.empty(); } // 获取队列大小 size_t size() const { std::lock_guard<std::mutex> lock(mtx); return data_queue.size(); } };

原理解释:

这个线程安全队列的实现主要通过以下几个关键组件实现同步和互斥:

  1. 互斥锁 (std::mutex): 保证每次只有一个线程可以执行入队或出队操作。
  2. 条件变量 (std::condition_variable): 用于在队列为空时阻塞出队线程,并在有新元素入队时唤醒等待的线程。
  3. 锁 (std::lock_guardstd::unique_lock): 自动管理互斥锁的锁定和解锁过程,确保即使在异常发生时也能正确释放互斥锁。

使用场景举例:

这种线程安全队列非常适合于生产者-消费者模型,其中多个生产者线程可以不断地向队列中添加任务,而多个消费者线程则从队列中取出并执行这些任务。通过使用线程安全队列,我们可以确保任务的添加和提取过程不会因并发操作而导致数据竞争或状态不一致的问题。

2024年6月29日 12:07 回复

你的答案