在C++中如何实现线程安全的队列

在这里插入图片描述

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》《C++》《Linux》《网络》 《redis学习笔记》

文章目录

  • 前言
  • 如何实现一个线程安全的队列思路
  • 应用场景
  • 代码实现
  • 总结


前言

在这里插入图片描述
在一次和豆包的模拟面试中,豆包问我:“在C++中,如何实现一个线程安全的队列呢?”


根据C++标准,STL容器的线程安全性遵循以下规则:

  • 只读操作是线程安全的:多个线程可以同时调用const 成员函数(如size, empty, at等)读取同一个容器,只要没有线程修改容器
  • 写操作需要独占访问:如果至少有一个线程在修改容器(如push_back, earse, operator[]等),其它线程必须通过同步机制,来保护对该容器的访问
  • 不同容器实例独立:不同线程操作不同的容器实例。

但如果多个线程同时修改同一个容器,或一个线程修改,另一个线程读取都是线程不安全的

在这里插入图片描述


如何实现一个线程安全的队列思路

实现步骤:

  1. 使用std::queue作为底层容器
  2. 使用std::mutex保护队列的访问
  3. 使用std::condition_variable协调线程,特别是在队列空时等待
  4. 在push时获取锁,添加元素后通知一个等待的线程
  5. 在pop时,使用while循环等待队列非空,处理虚假唤醒
  6. 提供tryPop和waitAndPop等不同方法,以适用不同场景
  7. 考虑异常安全,使用lock_guard或unique_lock管理锁的声明周期

在C++中实现线程安全队列的核心就在于通过同步机制保护共享数据的访问,并协调生产者和消费者线程操作


应用场景

  • 生产者-消费者模型:多个生产者线程向队列添加任务,消费者线程处理任务
  • 线程池任务队列:线程池使用线程安全的队列分发任务,支持异步返回值(std::future)
  • 事件驱动系统:管理异步事件,确保按顺序处理回调

代码实现

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

template <typename T>
class ThreadSafeQueue {
public:
    // 入队操作
    // 获取锁后添加元素,并通知一个等待线程
    void push(T value) {
        std::lock_guard<std::mutex> lock(_mtx);
        if(_finish)  
            return ;

        _data_queue.push(value);
        _cv.notify_one();
    };

    // 非阻塞出队
    // 立即尝试获取元素,若队列为空则返回失败
    bool tryPop(T& value) {
        std::lock_guard<std::mutex> lock(_mtx);
        if(_data_queue.empty() || _finish)
            return false;   // 队列为空 or 终止符为true
    
        value = _data_queue.front();
        _data_queue.pop();
        return true;
    };
    
    // 阻塞出队
    // 等待队列非空后获取元素,处理虚假唤醒
    void waitAndPop(T& value) {
        std::lock_guard<std::mutex> lock(_mtx);
        _cv.wait(lock, [this](){
            return !_data_queue.empty() || _finish;
        });

        if(finish)
            return ;
        value = _data_queue.front();
        _data_queue.pop();
        return ;
    };
        
    // 终止队列
    // 设置终止标志并唤醒所有线程
    void finish() {
        std::lock_guard<std::mutex> lock(_mtx);
        _finish = true;
        _cv.notify_all();
    };

    // 判断队列是否为空
    bool empty() const {
        std::lock_guard<std::mutex> lock(_mtx);
        return _data_queue.empty();
    };

    // 获取队列元素个数
    int size()  {
        std::lock_guard<std::mutex> lock(_mtx);
        return _data_queue.size();
    }
private:
    std::queue<T> _data_queue;       // 底层容器就是queue
    std::mutex _mtx;                 // 互斥锁
    std::condition_variable _cv;     // 信号量 
    bool _finish = false;            // 终止标志
};

在这里插入图片描述


总结

以上就是我总结的在C++中如何实现线程安全的队列

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/980350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全 | 漏洞挖掘】利用文件上传功能的 IDOR 和 XSS 劫持会话

未经许可,不得转载。 本文涉及漏洞均已修复。 文章目录 前言正文前言 想象这样一个场景:一个专门处理敏感文档的平台,如保险理赔或身份验证系统,却因一个设计疏漏而成为攻击者的“金矿”。在对某个保险门户的文件上传功能进行测试时,我意外发现了一个可导致大规模账户接管…

[操作系统] 文件的软链接和硬链接

文章目录 引言硬链接&#xff08;Hard Link&#xff09;什么是硬链接&#xff1f;硬链接的特性硬链接的用途 软链接&#xff08;Symbolic Link&#xff09;什么是软链接&#xff1f;软链接的特性软链接的用途 软硬链接对比文件的时间戳实际应用示例使用硬链接节省备份空间用软链…

c# winform程序 vs2022 打包生成安装包

最近&#xff0c;利用c# winform程序该客户开发一套进销存管理系统&#xff0c;项目在部署前&#xff0c;需要生成安装包&#xff0c;以便部署在客户电脑上面。总结步骤如下&#xff1a; 1、在打包之前 (VS中需要包括Microsoft visual studio installer projects扩展项目)&…

现今大语言模型性能(准确率)比较

现今大语言模型性能(准确率)比较 表头信息:表的标题为“大语言模型性能比较结果”(英文:Table 1: Large Language Model Performance Comparison Results),表明该表是用于对比不同大语言模型的性能。列信息: 模型:列出参与比较的不同大语言模型名称,包括LLAMA3(70B)…

Mysql-如何理解事务?

一、事务是什么东西 有些场景中&#xff0c;某个操作需要多个sql配合完成&#xff1a; 例如&#xff1a; 李四这个月剩下的前不够交房租了&#xff0c;找张三借1000元急用&#xff1a; &#xff08;1&#xff09;给张三的账户余额 减去1000元 updata 账户表 set money money -…

GitLab Pages 托管静态网站

文章目录 新建项目配置博客添加 .gitlab-ci.yml其他配置 曾经用 Github Pages 来托管博客内容&#xff0c;但是有一些不足&#xff1a; 在不科学上网的情况下&#xff0c;是没法访问的&#xff0c;或者访问速度非常慢代码仓库必须是公开的&#xff0c;如果设置为私有&#xff0…

智能图像处理平台:图片管理

接着我们讲图片管理&#xff0c;先实现图片基础的增删改查&#xff0c;再去考虑图像处理。 主要是&#xff0c;我们需要完成查询时&#xff0c;查询的图片的上传者的角色等级小于等于我们当前登陆账号。 后端controller&#xff1a; package com.llpp.controller;import cn.…

计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型音乐推荐系统 音乐数据分析 音乐可视化 音乐爬虫 知识图谱 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

《Python实战进阶》No 11:微服务架构设计与 Python 实现

第11集&#xff1a;微服务架构设计与 Python 实现 2025年3月3日更新了代码和微服务运行后的系统返回信息截图&#xff0c;所有代码在 python3.11.5虚拟环境下运行通过。 微服务架构通过将复杂应用拆分为独立部署的小型服务&#xff0c;显著提升了系统的可扩展性和维护性。本集…

NC2227_约瑟夫环

题解: import java.util.Scanner;​public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int k sc.nextInt();int m sc.nextInt();int set 0;for(int i 2;i < n;i ){set (set m) % i;}System.out.p…

openEuler操作系统

一、OpenEuler简介 OpenEuler 是一款由华为发起、社区驱动的开源 Linux 操作系统&#xff0c;专注于企业级应用场景(如服务器、云计算、边缘计算等)。其前身是华为的 EulerOS&#xff0c;2019 年正式开源并捐赠给开放原子开源基金会&#xff0c;旨在构建一个中立、开放的生态系…

vite+react+ts如何集成redux状态管理工具,实现持久化缓存

1.安装插件 这里的redux-persist--进行数据的持久化缓存&#xff0c;确保页面刷新数据不会丢失 yarn add react-redux^9.2.0 redux-persist^6.0.0 reduxjs/toolkit^2.5.1 2.创建仓库文件夹 在项目的src文件夹下创建名为store的文件夹&#xff0c;里面的具体文件如下 featur…

大模型function calling:让AI函数调用更智能、更高效

大模型function calling&#xff1a;让AI函数调用更智能、更高效 随着大语言模型&#xff08;LLM&#xff09;的快速发展&#xff0c;其在实际应用中的能力越来越受到关注。Function Calling 是一种新兴的技术&#xff0c;允许大模型与外部工具或API进行交互&#xff0c;从而扩…

图像分类项目1:基于卷积神经网络的动物图像分类

一、选题背景及动机 在现代社会中&#xff0c;图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用&#xff0c;例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类&#xff0c;可以帮助人们更好地了解动物种类、数量和分布情况&#xff0c;…

在 Ansys Maxwell 中分析磁场

在 Ansys Maxwell 中分析磁场 分析磁场的能力对于理解电磁系统至关重要。Ansys Maxwell 为工程师提供了强大的工具&#xff0c;帮助他们探索磁场数据并从中提取有价值的见解。在本指南中&#xff0c;我将深入研究 Ansys Maxwell 中的几种基本技术和方法&#xff0c;以有效地分…

[Lc滑动窗口_1] 长度最小的数组 | 无重复字符的最长子串 | 最大连续1的个数 III | 将 x 减到 0 的最小操作数

目录 1. 长度最小的字数组 题解 代码 ⭕2.无重复字符的最长子串 题解 代码 3.最大连续1的个数 III 题解 代码 4.将 x 减到 0 的最小操作数 题解 代码 1. 长度最小的字数组 题目链接&#xff1a;209.长度最小的字数组 题目分析: 给定一个含有 n 个 正整数 的数组…

数据库Redis数据库

目录 一、数据库类型 1、关系型数据库 2、非关系型数据库 3、关系型非关系型区别 二、Redis数据库 1、什么是Redis 3、Redis特点 4、Redis为什么读写快 5、部署Redis数据库 6、redis管理 7、Redis数据库五大类型 8、Redis数据库基础使用 9、redis五大类型增删查?…

蓝桥备赛(四)- 数组(下)

一 、 字符数组 1.1 介绍 数组的元素如果是字符类型 &#xff0c; 这种数组就是字符数组 &#xff0c; 字符数组可以是一维数组 &#xff0c; 可以是二维数组 (多维数组)。 接下来主要讨论一维的字符数组 : char arr1[5] //一维数组 char arr2[3][5] // 二维数组 C语言 中…

数据图表ScottPlot.WPF用法示例

目录 一、添加 NuGet 程序包&#xff08;5.0.47&#xff09; 二、MainWindow.xaml中添加引用 三、MainWindow.xaml.cs 具体使用代码 图表示例&#xff1a; 一、添加 NuGet 程序包&#xff08;5.0.47&#xff09; 二、MainWindow.xaml中添加引用 <Window x:Class"…

AtCoder Beginner Contest 001(A - 積雪深差、B - 視程の通報、C - 風力観測、D - 感雨時刻の整理)题目翻译

由于我发现网上很少有人会发很久之前AtCoder Beginner Contes的题&#xff0c;所以我打算从AtCoder Beginner Contest 001开始写。大约两周一更&#xff0c;需要的可以订阅专栏&#xff0c;感谢支持Thanks♪(&#xff65;ω&#xff65;)&#xff89; →题目讲解 A - 積雪深差 …