新闻中心

C++如何实现一个线程安全的队列_C++多线程编程与线程安全队列实现

2025-11-12
浏览次数:
返回列表
线程安全队列通过互斥锁和条件变量实现,支持多线程环境下安全的入队、出队操作,空队列时阻塞等待。

c++如何实现一个线程安全的队列_c++多线程编程与线程安全队列实现

在C++多线程编程中,线程安全的队列是常见的需求,尤其是在生产者-消费者模型中。要实现一个线程安全的队列,核心是保护共享数据不被多个线程同时访问导致竞争条件。通常使用互斥锁(std::mutex)配合条件变量(std::condition_variable)来实现高效、安全的操作。

基本设计思路

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

  • 多个线程可以安全地向队列中添加元素(入队)
  • 多个线程可以安全地从队列中取出元素(出队)
  • 当队列为空时,出队操作应阻塞等待,直到有新元素加入
  • 使用RAII机制自动管理锁,避免死锁

为此,我们封装一个模板类,内部使用 std::queue 存储数据,用 std::mutex 保护访问,用 std::condition_variable 实现线程等待与唤醒。

线程安全队列的实现代码

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

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

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

下面是一个简单的多线程测试例子,演示两个生产者线程和一个消费者线程共享同一个队列。

#include <iostream>

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 < 10; ++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 p2(producer, std::ref(queue));
    std::thread c1(consumer, std::ref(queue));

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

    return 0;
}

关键点说明

push() 使用 std::lock_guard 自动加锁,插入后调用 notify_one() 唤醒一个等待线程。如果多个消费者在等待,只会唤醒一个,避免惊群效应。

网趣购物系统加强升级版 网趣购物系统加强升级版

新版本程序更新主要体现在:完美整合BBS论坛程序,用户只须注册一个帐号,即可全站通用!采用目前流行的Flash滚动切换广告 变换形式多样,受人喜爱!在原有提供的5种在线支付基础上增加北京云网支付!对留言本重新进行编排,加入留言验证码,后台有留言审核开关对购物系统的前台进行了一处安全更新。在原有文字友情链接基础上,增加LOGO友情链接功能强大的6种在线支付方式可选,自由切换。对新闻列表进行了调整,

网趣购物系统加强升级版 0 查看详情 网趣购物系统加强升级版

wait_and_pop() 使用 std::unique_lock 配合 cv.wait(),只有当队列非空时才继续执行,否则阻塞。这比忙等更高效。

try_pop() 提供非阻塞版本,适合不需要等待的场景。

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

基本上就这些。这个实现简单、安全,适用于大多数多线程场景。如果需要更高性能,可考虑无锁队列(lock-free queue),但复杂度会显著上升。当前基于锁的方案在多数应用中已足够高效。

以上就是C++如何实现一个线程安全的队列_C++多线程编程与线程安全队列实现的详细内容,更多请关注其它相关文章!


# 死锁  # 建设银行信用卡网站  # seo推广的方式  # 德阳seo营销售后  # 代课教师网站建设ppt  # 达州网络推广网站  # 柳林镇seo网站推广  # 佛山全网营销seo推广机构  # 盐城网络营销推广与策划  # seo专员哪个地方好  # 海口英文网站建设  # 配置文件  # 怎么做  # 更快  # c++线程安全  # 升级版  # 互斥  # 购物系统  # 如何实现  # 多个  # 多线程  # 无锁  # stream  # ios  # c++  # ai  # 线程安全队列 


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


相关推荐: 护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  将HTML动态表格多行数据保存到Google Sheet的教程  126邮箱网页版官方入口 126邮箱账号在线登录平台  J*a递归快速排序中静态变量导致数据累积问题的解决方案  C++ vector二维数组定义_C++ vector of vector用法  Win11怎么开启卓越性能模式 Win11电源选项启用高性能释放硬件潜力【方法】  Android Studio计算器C键功能异常排查与修复教程  J*aScript设计模式实践_j*ascript代码优化  word邮件合并后日期格式不对怎么改_Word邮件合并日期格式修改方法  地铁跑酷免费秒玩入口链接 地铁跑酷小游戏免费秒玩网站  冬*霸灯泡不亮怎么办_浴霸取暖灯一盏不亮的灯座清洁修复法  J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析  在Socket.IO连接中实现Access Token自动更新与动态重连  怎样更改Windows系统的默认安装路径_避免C盘爆满的终极设置【技巧】  文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】  J*aScript中安全有效地处理localStorage字符串数据  腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录  Excel中VLOOKUP的第四个参数是干什么用的_Excel VLOOKUP第四参数作用解析  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】  PHP表单数据传递:如何通过隐藏输入字段获取动态ID  Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐  PHP中高效并行检查多链接状态的教程  J*aScript中高效管理与清空动态列表:避免循环陷阱  Safari自带网页翻译功能怎么用 无需插件轻松看懂外文网站【方法】  css绝对定位元素脱离父容器怎么办_确保父元素position非static  J*aScript DOM操作:高效清空列表元素的策略与实践  2025-2030年全球乘用车销量预测:新能源成增长主力  C++如何使用AddressSanitizer(ASan)_C++调试工具中检测内存访问错误的利器  C++如何比较两个字符串_C++ string compare函数与操作符对比  1688商家版怎样分析买家画像精准供货_1688商家版分析买家画像精准供货【供货策略】  sublime如何处理大型CSV文件的列对齐_sublime高级表格编辑插件指南  Win10如何恢复误删的快捷方式_Win10重建常用软件快捷方式  mcjs网页版流畅运行 mcjs低配电脑畅玩入口  b站怎么删除评论_b站评论管理与删除操作  如何创建独立于主系统的J*a运行环境_隔离式环境搭建策略  sublime怎么进行远程开发编辑_配置rsub/rmate实现sublime编辑服务器文件  Node.js 中使用 node-cron 实现定时 API 数据抓取与处理  哔哩哔哩忘记密码了怎么找回_哔哩哔哩密码找回方法  AO3中文官网链接_AO3网页版稳定镜像站  漫蛙manwa2最新登录网址_漫蛙manwa2手机网页版入口  如何在 Windows 11 中启动游戏手柄设置  使用 Pandas 高效处理 .dat 文件:数据清洗与数值计算实战  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  Win10磁盘清理工具在哪 Win10打开并使用磁盘清理【教程】  ArrayList与LinkedList核心操作的Big-O复杂度分析  Angular Material 垂直步进器:实现底部到顶部排序的教程  Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区  Yandex搜索引擎官方地址 俄罗斯网络世界的主要入口  抖音DOU+怎么投最有效 抖音付费推广的ROI提升技巧 

搜索