当前位置: 首页 > news >正文

C#线程 ConcurrentQueue安全队列介绍

https://blog.csdn.net/qq_41230604/article/details/126305068

C#线程安全队列ConcurrentQueue
ConcurrentQueue队列是一个高效的线程安全的队列,是Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据结构。

ConcurrentQueue内部结构:


实现原理
众所周知,在普通的非线程安全队列有两种实现方式:

1.使用数组实现队列。 2.使用链表实现队列。

看看两种方式的优劣:
  .Net Farmework中的普通队列Queue的实现使用了第一种方式,缺点是当队列空间不足会进行扩容,扩容的主要实现是开辟一个原始长度2倍的新数组,然后将原始数组里面的数据复制到新数组中,所以当扩容时就会产生不小的内存开销,在并发的环境中对性能的影响不可小视。当然在调用Queue的构造函数时可以指定默认空间的大小,但是一般情况下数据量是不可预测的,选大了会照成空间浪费,选小了会有复制内存的开销,而且队列扩容以后需要显示调用TrimToSize()方法才能回收掉不使用的内存空间。

  第二种链表实现方式虽然消除了空间浪费的问题但是又增加了GC的压力,当入队时会分配一个新节点,出队时要对该节点进行废弃,对于大量的出队入队操作时该实现方式性能不高。

  综合以上两种实现方式,在支持多线程并发出队并发入队的情况下,ConcurrentQueue使用了分段存储的概念(如上图所示),ConcurrentQueue分配内存时以段(Segment)为单位,一个段内部含有一个默认长度为32的数组和执行下一个段的指针,有个和Head和Tail指针分别指向了起始段和结束段(这种结构有点像操作系统的段式内存管理和页式内存管理策略)。这种分配内存的实现方式不但减轻的GC的压力而且调用者也不用显示的调用TrimToSize()方法回收内存(在某段内存为空时,会由GC来回收该段内存)。

Segment内部和用数组实现的普通队列相当,只不过对于入队和出队操作使用了原子操作来防止多线程竞争问题,使用随机退让等技术保证活锁等问题,实现机制和ConcurrentStack差别不大,跟多TryAppend的实现细节在源码注释中已经阐述的非常清楚这里就再做不过多的解释。

主要成员函数
入队(EnQueue) 、出队(TryDequeue) 、是否为空(IsEmpty)、获取队列内元素数量(Count)。

void Enqueue(T item) 入队函数

public void Enqueue(T item)
{
    Spinwait spin = new Spinwait();
    while (true)
    {
        Segment tail =m_tail;
        if ( tail .TryAppend(item))
        return;
        spin.SpinOnce();
    }
}

如上代码所示,入队操作是在尾部的段中进行,当数据进入段内失败时会先进行一个回退操作然后再不断尝试直到成功,这里失败的原因(tail.Append(item)返回false)只有一个就是当该段内的空间不够时正在分配新的段,这段时间内会进入该段的元素会失败。
当队列已满时会自动增加队列容量。

bool TryDequeue(T result) 出队函数
尝试出队函数,如果当前队列为空,返回false,否则返回队列的第一个元素。

public bool TryDequeue(out T result)
{
    while (!IsEmpty)
    {
        Segment head = m_head;
        if (head.TryRemove(out result))
            return true;
    }

    result = default(T);
    return false;
}

如上代码所示,出队失败时返回false 而不是像入队一样进行回退操作,因为出队失败的原因只有一个就是当队列内所有段的元素为空时,所以出队设计成了返回bool值的函数。

bool TryPeek(T * result)
跟TryDequeue()方法相似,但不删除队列中的元素。

int Count()
返回当前队列中元素的个数。

找到头节点的low的位置和尾节点的high的位置,由于每个段内记录了当前段在队列中的索引,所以很容易求出整个队列中元素的数量。

跟ConcurrentStack一样 微软官方文档和注释中也说明:判断队列是否为空要使用IsEmpty属性而不是判断Count == 0 原因在于GetHeadTailPositions在大量数据入队和出队的过程中寻找头尾节点的位置是比较耗时的操作,要不断循环确定头尾节点的位置,所以判断队列是否为空还是使用IsEmpty属性。

bool IsEmpty()
判定当前队列为空。

整个判断主要有三种情况:
1.头节点(段)不为空返回false
2.头节点为空而且下一个节点也为空返回true
3.头节点为空而且下一个节点不为空返回false,这种情况说明队列正在扩容,所以要自选等待扩容完毕时再次进行判断

void Reset()
清空并复位队列。

相关文章:

C#线程 ConcurrentQueue安全队列介绍

https://blog.csdn.net/qq_41230604/article/details/126305068 C#线程安全队列ConcurrentQueue ConcurrentQueue队列是一个高效的线程安全的队列,是Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据结构。 ConcurrentQueue内部结…...

CURL踩坑记录

因为项目使用的windows server,且没有安装Postman,所以对于在本地的Postman上执行的请求,要拷贝到服务器执行,只能先转化成为curl命令,操作也很简单,如下: 注意,Postman默认对url包围…...

Python 自动化(十八)admin后台管理

admin后台管理 什么是admin后台管理 django提供了比较完善的后台数据库的接口,可供开发过程中调用和测试使用 django会搜集所有已注册的模型类,为这些模型类提供数据管理界面,供开发使用 admin配置步骤 创建后台管理账号 该账号为管理后…...

Navicat 技术指引 | 适用于 GaussDB 的自动运行功能

Navicat Premium(16.2.8 Windows版或以上) 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结构同步、协同合作、数据迁移等),这…...

MySQL 的执行原理(四)

5.5. MySQL 的查询重写规则 对于一些执行起来十分耗费性能的语句,MySQL 还是依据一些规则,竭尽全力的把这个很糟糕的语句转换成某种可以比较高效执行的形式,这个过程也可以 被称作查询重写。 5.5.1. 条件化简 我们编写的查询语句的搜索条件…...

PHP 正则式 全能匹配URL(UBB)

PHP 正则式 全能匹配URL(UBB) 语言:PHP 注明:正则式 无语言限制(js、PHP、JSP、ASP、VB、.net、C#...)一切皆可。 简介:PHP UBB 正则式 全能匹配URL 自动加超级链接。网上找了很多都不匹配或…...

hadoop shell操作 hdfs处理文件命令 hdfs上传命令 hadoop fs -put命令hadoop fs相关命令 hadoop(十三)

hadoop fs -help rm 查看rm命令作用 hadoop fs 查看命令 1. 创建文件夹: # hdfs前缀也是可以的。更推荐hadoop hadoop fs -mkdir /sanguo 2.上传至hdfs命令: 作用: 从本地上传hdfs系统 (本地文件被剪切走,不存在了&…...

redis-cluster集群

1.redis-cluster集群 redis3.0引入的分布式存储方案 集群由多个node节点组成,redis数据分布在这些节点之中。 在集群之中分为主节点和从节点 集群模式当中,主从一一对应,数据写入和读取与主从模式一样,主负责写,从…...

Hfish安全蜜罐部署

一、Hfish蜜罐介绍 HFish蜜罐官网 HFish是一款社区型免费蜜罐,侧重企业安全场景,从内网失陷检测、外网威胁感知、威胁情报生产三个场景出发,为用户提供可独立操作且实用的功能,通过安全、敏捷、可靠的中低交互蜜罐增加用户在失陷…...

Apache POI(Java)

一、Apache POI介绍 Apache POI是Apache组织提供的开源的工具包(jar包)。大多数中小规模的应用程序开发主要依赖于Apache POI(HSSF XSSF)。它支持Excel 库的所有基本功能; 文本的导入和导出是它的主要特点。 我们可以使用 POI 在…...

P8599 [蓝桥杯 2013 省 B] 带分数(dfs+全排列+断点判断)

思路&#xff1a;1.深度枚举所有排列情况 2.设置为每个排列设置两个断点&#xff0c;分为三部分&#xff1a;a,b,c 3.转换为乘法判断条件&#xff0c;满足加一 代码如下&#xff1a;&#xff08;可用next_permutation全排列函数代替dfs&#xff09; #include<iostream>…...

PS右边的图层窗口没有显示出来?

问题描述&#xff1a;PS右边的图层窗口没有显示出来&#xff1f; 解决步骤&#xff1a; 键盘F7快捷键即可调出来。...

Sealos 云操作系统私有化部署教程

Sealos 私有云已经正式发布了&#xff0c;它为企业用云提供了一种革命性的新方案。Sealos 的核心优势在于&#xff0c;它允许企业在自己的机房中一键构建一个功能与 Sealos 公有云完全相同的私有云。这意味着企业可以在自己的控制和安全范围内&#xff0c;享受到公有云所提供的…...

信息系统的安全保护等级的五个级别

信息系统的安全保护等级分为五级&#xff1a;第一级为自主保护级、第二级为指导保护级、第三级为监督保护级、第四级为强制保护级、第五级为专控保护级。 法律依据&#xff1a;《信息安全等级保护管理办法》第四条 信息系统的安全保护等级分为以下五级&#xff1a;   &#…...

c语言使用modbus库

Modbus是一种串行通信协议&#xff0c;被广泛用于连接工业电子设备。Modbus库可以提供用于实现Modbus通信的功能。 以下是一个简单的示例&#xff0c;展示了如何在C语言中使用Modbus库来读取一个Modbus设备中的保持寄存器。 #include <stdio.h> #include <modbus.…...

【Flask使用】全知识md文档,4大部分60页第3篇:Flask模板使用和案例

本文的主要内容&#xff1a;flask视图&路由、虚拟环境安装、路由各种定义、状态保持、cookie、session、模板基本使用、过滤器&自定义过滤器、模板代码复用&#xff1a;宏、继承/包含、模板中特有变量和函数、Flask-WTF 表单、CSRF、数据库操作、ORM、Flask-SQLAlchemy…...

芯片的测试方法

半导体的生产流程包括晶圆制造和封装测试&#xff0c;在这两个环节中分别需要完成晶圆检测(CP, Circuit Probing)和成品测试(FT, Final Test)。无论哪个环节&#xff0c;要测试芯片的各项功能指标均须完成两个步骤&#xff1a;一是将芯片的引脚与测试机的功能模块连接起来&…...

网络安全等级保护2.0国家标准

等级保护2.0标准体系主要标准如下&#xff1a;1.网络安全等级保护条例2.计算机信息系统安全保护等级划分准则3.网络安全等级保护实施指南4.网络安全等级保护定级指南5.网络安全等级保护基本要求6.网络安全等级保护设计技术要求7.网络安全等级保护测评要求8.网络安全等级保护测评…...

从根到叶:随机森林模型的深入探索

一、说明 在本综合指南中&#xff0c;我们将超越基础知识。当您盯着随机森林模型的文档时&#xff0c;您将不再对“节点杂质”、“加权分数”或“成本复杂性修剪”等术语感到不知所措。相反&#xff0c;我们将剖析每个参数&#xff0c;阐明其作用和影响。通过理论和 Python 实践…...

python数据结构与算法-15_堆与堆排序

堆(heap) 前面我们讲了两种使用分治和递归解决排序问题的归并排序和快速排序&#xff0c;中间又穿插了一把树和二叉树&#xff0c; 本章我们开始介绍另一种有用的数据结构堆(heap)&#xff0c; 以及借助堆来实现的堆排序&#xff0c;相比前两种排序算法要稍难实现一些。 最后我…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...