多线程操作中实现队列Push函数的阻塞等待(队列大小超5)
实现队列满时阻塞Push的多线程安全队列
你的需求是让自定义队列在大小超过5时,PushItem进入等待状态,直到队列有空闲空间(大小≤5)。下面是修改后的完整实现,同时修复了原代码中的几个线程安全问题:
template <typename T> class CAMERA_DATA_QUEUE { private: std::queue<T> m_queue; std::mutex m_mutex; std::condition_variable m_cond; // 定义队列最大容量,方便后续修改 const int MAX_SIZE = 5; public: void PushItem(T item) { std::unique_lock<std::mutex> lock(m_mutex); // 等待队列大小不超过最大容量 m_cond.wait(lock, [this]() { return m_queue.size() <= MAX_SIZE; }); m_queue.push(std::move(item)); // 用move减少拷贝,优化性能 m_cond.notify_one(); // 通知可能等待的Pop线程 } T Pop() { std::unique_lock<std::mutex> lock(m_mutex); // 等待队列不为空 m_cond.wait(lock, [this]() { return !m_queue.empty(); }); T item = std::move(m_queue.front()); m_queue.pop(); m_cond.notify_one(); // 通知可能等待的Push线程(队列有空间了) return item; } void ResetQueue() { std::unique_lock<std::mutex> lock(m_mutex); // 清空队列原内容 std::queue<T> empty_queue; std::swap(m_queue, empty_queue); // 通知所有等待的线程(Push线程现在可以继续了) m_cond.notify_all(); } int GetSize() { // 加锁保证线程安全,避免读取size时队列被其他线程修改 std::lock_guard<std::mutex> lock(m_mutex); return m_queue.size(); } };
关键修改说明:
PushItem的阻塞逻辑:
- 使用
std::condition_variable::wait等待队列大小不超过5,wait会自动释放锁并进入休眠,直到条件满足(队列size≤5)时重新获取锁,保证线程安全。 - 用
std::move传递item,避免不必要的拷贝,提升性能。
- 使用
Pop后的通知:
- 弹出元素后,队列空闲空间增加,必须调用
notify_one通知等待的Push线程,让它们检查是否可以继续入队。
- 弹出元素后,队列空闲空间增加,必须调用
修复ResetQueue:
- 原代码中
m_queue.empty()只是判断是否为空,并没有清空队列,这里用swap替换为空队列来清空内容。 - 清空后调用
notify_all,唤醒所有等待的Push和Pop线程,避免线程永久阻塞。
- 原代码中
线程安全的GetSize:
- 给
GetSize加锁,因为m_queue.size()不是线程安全的操作,必须在锁保护下读取。
- 给
内容的提问来源于stack exchange,提问作者sumit kang
相关产品推荐
相关产品推荐

