新闻中心

c++中如何实现一个线程安全队列_c++中线程安全队列实现方法与示例

2025-11-05
浏览次数:
返回列表
线程安全队列通过互斥锁和条件变量实现,保证多线程环境下数据一致性。使用std::mutex保护共享队列,std::condition_variable实现线程间通信,push操作入队后唤醒等待线程,wait_and_pop阻塞等待非空,try_pop提供非阻塞尝试,支持多生产者多消费者场景,避免竞争与忙等待,确保高效同步。

c++中如何实现一个线程安全队列_c++中线程安全队列实现方法与示例

在C++中实现一个线程安全队列,核心是保护共享数据不被多个线程同时访问导致竞争。通常使用互斥锁(std::mutex)配合条件变量(std::condition_variable)来实现高效的阻塞式队列。这种方式既能保证线程安全,又能避免忙等待。

基本设计思路

线程安全队列需要满足以下几点:

  • 对队列的入队(push)和出队(pop)操作加锁,防止数据竞争
  • 使用条件变量通知等待的线程,有新元素入队
  • 支持多生产者、多消费者场景
  • 避免死锁,锁的粒度要合理

实现代码示例

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

template<typename T>
class ThreadSafeQueue {
private:
    std::queue<T> data_queue;
    mutable std::mutex mtx;
    std::condition_variable cv;

public:
    ThreadSafeQueue() = default;

    void push(T value) {
        std::lock_guard<std::mutex> lock(mtx);
        data_queue.push(std::move(value));
        cv.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);
        cv.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();
    }
};

使用示例:生产者-消费者模型

void producer(ThreadSafeQueue<int>& queue) {
    for (int i = 0; i < 5; ++i) {
        queue.push(i);
        std::cout << "Produced: " << i << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void consumer(ThreadSafeQueue<int>& queue) {
    for (int i = 0; i < 5; ++i) {
        int value;
        queue.wait_and_pop(value);
        std::cout << "Consumed: " << value << "\n";
    }
}

int main() {
    ThreadSafeQueue<int> queue;

    std::thread p1(producer, std::ref(queue));
    std::thread c1(consumer, std::ref(queue));

    p1.join();
    c1.join();

    return 0;
}

该程序输出类似:

Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
...

关键点说明

push() 中使用 notify_one() 及时唤醒一个等待线程,避免消费者长时间挂起。

刺鸟创客 刺鸟创客

一款专业高效稳定的AI内容创作平台

刺鸟创客 110 查看详情 刺鸟创客

wait_and_pop() 使用 unique_lock 配合条件变量,能够在队列为空时自动阻塞,直到有数据可用。

try_pop() 提供非阻塞方式获取元素,适用于需要轮询但不想阻塞的场景。

所有公共方法都通过锁保护内部队列,确保任意时刻只有一个线程能修改或读取数据。

基本上就这些。这个实现简单、高效,适合大多数多线程应用场景。

以上就是c++++中如何实现一个线程安全队列_c++中线程安全队列实现方法与示例的详细内容,更多请关注其它相关文章!


# 库中  # 目录优化的网站  # 洛阳网站建设选哪家  # 推广网站建设功能介绍  # 乐至网站建设和优化  # 推销推广营销  # 品牌网站推广指标  # 焦作seo公司选择21火星  # seo优化用来干嘛的  # 网站的优化推举火31星  # 宜宾seo推广价格  # 多个  # 互斥  # c++  # 游戏开发  # 重写  # 死锁  # 数据结构  # 多线程  # 如何使用  # 如何实现  # stream  # ios  # ai  # 线程安全队列 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Win10磁盘清理工具在哪 Win10打开并使用磁盘清理【教程】  MAC如何安全彻底地删除文件_MAC使用终端命令确保文件无法被恢复  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  Python异步编程实践:使用Binance API构建实时交易数据流  在J*a中如何开发简易仓库管理与库存统计_仓库管理库存统计项目实战解析  Django表单提交验证失败后保持字段值不刷新  163邮箱网页版入口导航平台 163邮箱网页版登录入口官网导航  J*aScript中在Map循环中检测并处理空数组元素  Win11怎么开启省电模式_Win11电池节电模式自动开启  C++ vector二维数组定义_C++ vector of vector用法  age动漫网站入口 age动漫官网直接访问入口  J*a最大堆Heapify方法修复:索引计算与边界条件深度解析  深入理解Google Cloud Datastore查询:祖先路径与数据一致性  1688商家版怎样分析买家画像精准供货_1688商家版分析买家画像精准供货【供货策略】  如何在Promise链中有效终止错误处理后的执行  Animex动漫社网入口地址 Animex动漫社网正版在线入口  海棠账号登录入口_登录海棠账户同步阅读记录  Surface怎么安装系统 微软Surface Pro U盘重装win11教程  PHP中高效并行检查多链接状态的教程  qq游戏大厅官方下载_qq游戏免费下载安装入口  在J*a中如何使用Stream.map转换元素_Stream映射操作解析  邮政编码查询不到怎么办_邮政编码查询不到的常见原因与对策  c++中的std::launder有什么实际用途_c++对象生命周期与指针优化  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  qq浏览器如何查看和导出已保存的密码 qq浏览器密码管理器数据备份教程  J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程  iCloud登录入口网页版 苹果iCloud官网登录  TikTok搜索不到用户发布内容怎么办 TikTok用户内容搜索优化方法  sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置  蛙漫官网漫画入口地址_蛙漫在线畅读无广告弹窗  荣耀Play7T运行卡顿解决_荣耀Play7T性能优化  小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口  Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】  《主播少女的秘密账号迷宫》首支宣传片  mysql备份恢复性能优化_mysql备份恢复性能优化方法  顺丰快递查询系统 官方正版查询入口  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  如何创建独立于主系统的J*a运行环境_隔离式环境搭建策略  谷歌邮箱网页版官方页面入口 谷歌邮箱网页端快速访问  Win11怎么关闭快速启动_Win11彻底关机设置教程  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  jQuery Mask 插件中实现电话号码固定前导零的教程  Lar*el 8 多关键词数据库搜索优化实践  汽水音乐车机版8.9下载 汽水音乐车机版8.9版本安装入口  Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖  如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension  高德地图公交到站提醒失败如何解决 高德提醒权限设置  如何有效阻止外部脚本意外修改内联样式的高度属性  Golang如何实现Web接口签名验证_Golang Web接口签名校验开发方法  深入理解Go语言中的指针类型:以*string为例 

搜索