信息发布→ 登录 注册 退出

c++ 怎么实现一个阻塞队列_c++多线程通信与阻塞队列实现方法

发布时间:2025-11-18

点击量:
阻塞队列通过互斥锁和条件变量实现线程安全的生产者-消费者模型,支持固定容量下的阻塞插入与提取,适用于任务调度与线程间通信。

c++ 怎么实现一个阻塞队列_c++多线程通信与阻塞队列实现方法

在C++多线程编程中,阻塞队列是线程间通信的常用工具。它允许一个或多个生产者线程向队列添加数据,同时一个或多个消费者线程从队列获取数据。当队列为空时,消费者线程会被阻塞,直到有新数据进入;当队列满时(如果是有界队列),生产者线程也会被阻塞,直到有空间可用。

使用标准库实现阻塞队列

借助 std::queuestd::mutexstd::condition_variablestd::unique_lock,可以轻松实现一个线程安全的阻塞队列。

示例代码:

#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>

template<typename T>
class BlockingQueue {
private:
    std::queue<T> data_queue;
    mutable std::mutex mtx;
    std::condition_variable not_empty;
    std::condition_variable not_full;
    size_t max_size;

public:
    explicit BlockingQueue(size_t max_sz = 1000) : max_size(max_sz) {}

    void push(const T& item) {
        std::unique_lock<std::mutex> lock(mtx);
        not_full.wait(lock, [this] { return data_queue.size() < max_size; });
        data_queue.push(item);
        not_empty.notify_one();
    }

    void pop(T& item) {
        std::unique_lock<std::mutex> lock(mtx);
        not_empty.wait(lock, [this] { return !data_queue.empty(); });
        item = data_queue.front();
        data_queue.pop();
        not_full.notify_one();
    }

    bool try_pop(T& item) {
        std::unique_lock<std::mutex> lock(mtx);
        if (data_queue.empty()) {
            return false;
        }
        item = data_queue.front();
        data_queue.pop();
        not_full.notify_one();
        return true;
    }

    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();
    }
};

多线程通信场景中的使用方式

阻塞队列常用于生产者-消费者模型。以下是一个简单示例,展示两个线程如何通过阻塞队列通信。

int main() {
    BlockingQueue<int> queue(5);  // 最多容纳5个元素

    std::thread producer([&]() {
        for (int i = 0; i < 10; ++i) {
            queue.push(i);
            std::cout << "生产: " << i << "\n";
        }
    });

    std::thread consumer([&]() {
        for (int i = 0; i < 10; ++i) {
            int value;
            queue.pop(value);
            std::cout << "消费: " << value << "\n";
        }
    });

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

    return 0;
}

关键点说明与建议

实现阻塞队列时需要注意几个核心机制:

Whimsical Whimsical

Whimsical推出的AI思维导图工具

Whimsical 182 查看详情 Whimsical
  • 条件变量等待必须用循环或 wait 的谓词形式:防止虚假唤醒导致问题。
  • 每次修改队列前必须加锁:保证对 queue 的操作是原子的。
  • 通知机制要正确触发:push 后 notify not_empty,pop 后 notify not_full。
  • 可选支持 try_pop 或超时 pop:提高灵活性,避免无限等待。

如果需要无界队列,可以去掉 max_size 限制和 not_full 条件变量,只保留 not_empty 即可。

应用场景与扩展思路

阻塞队列广泛应用于任务调度、日志系统、消息中间件等场景。

  • 可用于线程池中任务队列的实现。
  • 结合 shared_ptr 支持对象传递,避免拷贝开销。
  • 增加 shutdown 标志位,支持优雅关闭队列,唤醒所有等待线程。

基本上就这些。只要理解了互斥锁和条件变量的协作机制,阻塞队列的实现并不复杂,但非常实用。

以上就是c++++ 怎么实现一个阻塞队列_c++多线程通信与阻塞队列实现方法的详细内容,更多请关注其它相关文章!


相关文章: 将JSON对象数组转置为键值对列表的实用指南  Win11怎么设置开机NumLock亮 Win11修改注册表InitialKeyboardIndicators值  Win10如何开启蓝牙功能_Windows10找不到蓝牙开关解决方法  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】  age动漫网站入口 age动漫官网直接访问入口  c++如何使用Meson构建系统_c++比CMake更快的构建工具  葱吃多了会怎样 葱吃多了会伤胃吗  铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧  解决Flask中Quill编辑器内容提交失败及TypeError的指南  Spyder启动失败:字体文件权限拒绝错误解决方案  QQ邮箱网页版入口登录 QQ邮箱在线邮箱官方通道  c++ dfs和bfs代码 c++深度广度优先搜索算法  Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践  构建轻量级网站内部消息系统:Formspree 集成指南  如何将HTML表格多行数据保存到Google Sheet  PDO预处理语句中冒号的正确处理:区分SQL函数格式与命名占位符  Golang并发任务中错误如何聚合_Golang goroutine error收集方式  Lar*el表单中优雅地处理“返回”按钮以规避验证:最佳实践指南  迅雷下载到U盘速度很慢怎么办_迅雷U盘下载慢优化方法  Go语言:非阻塞式判断标准输入(os.Stdin)是否有数据  Mac怎么使用表情符号_Mac Emoji快捷键面板  Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】  Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧  绝地鸭卫平a核爆刀流玩法攻略  HTML5原生日期选择器与jQuery UI:实现日期选择器的联动与程序化控制  Lar*el Eloquent:高效统计带条件关联模型的数量  小米14应用无法联网原因分析_小米14网络权限修复  “音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!  Composer的 "conflict" 字段有什么用_如何声明不兼容的包以避免依赖冲突  荒野行动PC版怎么注册_荒野行动PC版账号注册详细流程图文教程  拼多多视频播放卡顿如何处理 拼多多视频播放优化技巧  网站内容防复制粘贴的实现策略与局限性  Win10快速启动功能利弊分析 Win10开启或关闭快速启动教程【技巧】  ArrayList与LinkedList操作复杂度详解:遍历与修改  J*a里如何使用forEach遍历Map_Map遍历方法说明  在VS Code中配置和运行Dart程序的完整步骤  qq游戏手机版下载安装_qq游戏移动端入口  荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】  Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性  J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程  UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】  J*a中实现Go语言select通道多路复用机制  html怎么运行外部js文件中的函数_运html外js文件函数法【技巧】  漫蛙MANWA漫画主页官方入口 漫蛙漫画最新在线阅读地址  uc浏览器网页版入口 uc浏览器网页版最新网址  J*aScript中正确使用querySelectorAll与复杂CSS选择器  谷歌浏览器最新官方入口链接 谷歌浏览器网页版官网导航  PHP文件上传至S3:策略、考量与避免本地存储的挑战  TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法 

在线客服
服务热线

服务热线

4008988990

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!