C#开发基础之单例模式下的集合数据,解决并发访问读写冲突的问题

在这里插入图片描述

1. 前言

在C#中,使用单例模式管理集合数据时,如果多线程同时访问集合,容易产生并发访问的读写冲突问题。单例模式下集合数据的并发访问读写冲突是如何产生的?

单例模式确保一个类在整个应用运行期间只有一个实例,这使得单例对象成为全局共享的资源。当这个单例对象包含集合数据(如List、Dictionary等),并且这些集合数据被多个线程同时访问时,就可能产生并发读写冲突。

2. 并发读写冲突

并发读写冲突通常发生在以下几种情况:

  • 写-写冲突:两个或多个线程同时尝试修改集合中的数据。例如,一个线程正在向集合中添加元素,而另一个线程试图删除元素,或者两个线程同时添加元素,可能导致元素丢失、重复或破坏集合的内部结构。
  • 读-写冲突:一个线程正在读取集合中的数据,而另一个线程同时修改集合(如添加、删除或更新元素)。这可能导致读取线程看到不一致的数据状态,即所谓的“脏读”。
  • 复合操作的不完整性:当一个操作需要多个步骤完成(如先检查元素是否存在再删除),如果在这过程中被其他线程打断,可能导致不符合预期的结果。
    在单例模式下,如果没有适当的并发控制措施(如锁、同步块、线程安全集合等),这些问题就会变得尤为突出,因为所有对集合的操作都集中在一个共享实例上。

3. 解决策略

为了避免这些问题,可以采取以下几种策略:

  • 使用锁:在访问集合的读写操作前后加锁,确保同一时间只有一个线程能访问集合。这可以是传统的锁机制,如C#中的lock语句关键字。
  • 使用线程安全的集合:许多编程语言提供了专为并发访问设计的线程安全集合,如C#中的ConcurrentDictionary等,这些集合内部实现了必要的同步机制。
  • 不可变集合:使用不可变集合可以在一定程度上避免写冲突,因为一旦创建,集合就不能被改变,只能通过操作返回新的集合实例。但这通常适用于读多写少的场景。
  • 副本和快照:在需要修改集合时,先创建集合的一个副本,然后在副本上操作,最后替换原集合。这种方式减少了锁的范围和时间,但可能增加内存开销。

4. 编码实践

1. 使用lock关键字

在这里插入图片描述
可以使用 lock 关键字来同步对集合的访问。lock 能确保在同一时刻只有一个线程能够访问被锁定的代码块,从而避免并发冲突。

public sealed class Singleton
{private static readonly Singleton instance = new Singleton();private List<int> data = new List<int>();private static readonly object lockObject = new object();private Singleton() {}public static Singleton Instance{get { return instance; }}public void AddData(int value){lock (lockObject){data.Add(value);}}public List<int> GetData(){lock (lockObject){// 返回副本,防止外部修改原始数据return new List<int>(data);}}
}

2. 使用ConcurrentDictionary或ConcurrentBag

在这里插入图片描述
.NET 提供了一些线程安全的集合类,如 ConcurrentDictionary 和 ConcurrentBag。这些集合类内置了线程同步机制,可以直接使用。

public sealed class Singleton
{private static readonly Singleton instance = new Singleton();private ConcurrentBag<int> data = new ConcurrentBag<int>();private Singleton() {}public static Singleton Instance{get { return instance; }}public void AddData(int value){data.Add(value);}public List<int> GetData(){return data.ToList();}
}

3. 使用ReaderWriterLockSlim

在这里插入图片描述

ReaderWriterLockSlim 允许多个线程同时读取,但写操作是独占的。这种锁非常适合读多写少的场景。

public sealed class Singleton
{private static readonly Singleton instance = new Singleton();private List<int> data = new List<int>();private static readonly ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();private Singleton() {}public static Singleton Instance{get { return instance; }}public void AddData(int value){lockSlim.EnterWriteLock();try{data.Add(value);}finally{lockSlim.ExitWriteLock();}}public List<int> GetData(){lockSlim.EnterReadLock();try{return new List<int>(data);}finally{lockSlim.ExitReadLock();}}
}

4. 使用ImmutableCollection

在这里插入图片描述

ImmutableCollection 提供了线程安全的集合操作。集合的每次修改都会创建一个新的集合,原有集合保持不变。

public sealed class Singleton
{private static readonly Singleton instance = new Singleton();private ImmutableList<int> data = ImmutableList<int>.Empty;private static readonly object lockObject = new object();private Singleton() {}public static Singleton Instance{get { return instance; }}public void AddData(int value){lock (lockObject){data = data.Add(value);}}public ImmutableList<int> GetData(){// 不需要锁,因为 ImmutableList 是不可变的return data;}
}

5. 总结

以上几种方法可以有效解决单例模式下集合数据的并发访问问题。具体选择哪种方法取决于你的应用场景和性能需求。如果写操作较少,读操作较多,可以选择 ReaderWriterLockSlim 或 ImmutableCollection。如果需要较高的写性能,可以考虑使用 ConcurrentDictionary 或 ConcurrentBag。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《华为 eNSP 模拟器安装教程》

1.电脑安装环境要求&#xff1a; 检查电脑是否安装过 eNSP 和依赖软件&#xff0c;如果有&#xff0c;请全部卸载。 安装软件列表&#xff1a; 2.软件安装&#xff1a; 安装 WinPcap&#xff1a; 打开安装包&#xff0c;单击【Next】 单击【I Agree】 单击【Install】 单击【…

supermap iclient3d for cesium场景加载雨雪效果,并加载相应材质

首先新建一个文件夹来存放材质&#xff0c;我选择src/assets/MaterialJson snow.json,复制粘贴,雨雪用一个就行了 {"material": {"id": "DA82AFCB-129A-4E66-995A-9F519894F58D","cullMode": "none","alphaMode"…

OpenCV结构分析与形状描述符(19)查找二维点集的最小面积外接旋转矩形函数minAreaRect()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 找到一个包围输入的二维点集的最小面积旋转矩形。 该函数计算并返回指定点集的最小面积边界矩形&#xff08;可能是旋转的&#xff09;。开发者…

prompt实用技巧-AI+Mermaid【酷炫钉钉文档】

AI 新技能&#xff0c;最近 chatGPTo1 发布后模型能力出现了新的跨越&#xff0c;之前模型的一本正经的胡说八道幻想模式&#xff0c;让AI 对待理科推理明显弱于文案的 AGI 的生成。 prompt engineer 工程师程序员的福音 prompt 内容如下&#xff0c; 按照以上格式生成创建公…

2024年华为9月4日秋招笔试真题题解

2024年华为0904秋招笔试真题 二叉树消消乐好友推荐系统维修工力扣上类似的题--K站中转内最便宜的航班 二叉树消消乐 题目描述 给定原始二叉树和参照二叉树(输入的二叉树均为满二叉树&#xff0c;二叉树节点的值范围为[1,1000]&#xff0c;二叉树的深度不超过1000)&#xff0c…

【信创】Linux上图形化多ping工具--gping的编译安装与打包 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【信创】图形化多ping工具gping的编译安装与打包 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在Linux操作系统上使用gping的文章。gping是一款非常实用的命令行工具&#xff0c;它将传统的ping命令进行了可视化改进…

『功能项目』切换职业面板【48】

我们打开上一篇47技能冷却蒙版的项目&#xff0c; 本章要做的事情是切换职业UI面板的功能 首先双击打开Canvas预制体在左上主角面板信息中新建一个button按钮 重命名&#xff08;父物体是按钮Button&#xff0c;子物体Image即可&#xff09; 创建一个Image 设计一下布局 复制三…

窗口嵌入桌面背景层(vb.net,高考倒计时特供版)

开发思路 根据系统生成高考倒计时的具体时间&#xff0c;附加江苏省省统考的时间生成算法&#xff0c;并且用户可以根据实际情况调整前后30天&#xff0c;具有丰富多彩的图片库和强大的自定义功能&#xff0c;效果图见P3 目前程序处于正式版的1.4版本&#xff0c;本程序由本作…

supermap Iclient3d for cesium加载地形并夸大地形

先看效果图 这是没有夸张之前的都江堰 这是夸大五倍后的都江堰 下面展示代码 主要就是加载supermaponline的skt地形然后夸大 <template><div class"PartOneBox"><div id"cesiumContainer"></div></div> </template>…

个人随想-向量数据库,你到底应该选择谁?

随着大模型的新起&#xff0c;vectorstore这1、2年也非常的火。从以前只能用chroma到现在几十种向量数据库&#xff0c;选都选不过来。 以我接触过的很多公司来说&#xff0c;他们去选择向量数据库的时候&#xff0c;很多都和迷茫&#xff0c;不知道应该选择哪个向量数据库&am…

自动驾驶自动泊车场景应用总结

自动泊车技术是当前智能驾驶技术的一个重要分支,其目标是通过车辆自身的感知、决策和控制系统,实现车辆在有限空间内的自主泊车操作。目前自动泊车可分为半自动泊车、全自动泊车、记忆泊车、自主代客泊车四种产品形态,其中, 根据搭载传感器和使用场景的不同,全自动泊车又可…

文本到3D生成

文本到3D生成是一种通过文本描述直接创建三维数字模型的技术。这种技术能够将语言描述转换成可视化的三维模型&#xff0c;使得内容创作者和设计师可以直接从概念阶段跳转到三维可视化&#xff0c;大大加快创作流程并提供更直观的设计和修改过程。 该技术的核心应用之一是基于…

无人直播好帮手,视频指定词语消音,消除违禁词,直播视频录制,音视频分离,分段

1.视频消音功能 一键删除或者静音视频中的词语 2.直播视频录制功能 可同时录制多个平台,多个主播,没有数量限制 3.音视频转码 支持多种音视频格式转换 4.视频频分离 分离视频中的音频和视频 5.视频合并分割 合并和按时间分割视屏 目前正在测试中…如有需要可以先使…

Netty笔记07-粘包与半包(上)

文章目录 前言1. 粘包造成粘包的原因解决粘包的方法 2. 半包造成半包的原因解决半包的方法 粘包现象服务端代码示例客户端代码示例 半包现象现象分析粘包半包滑动窗口MSS 限制Nagle 算法 前言 粘包和半包问题是网络编程中常见的问题&#xff0c;特别是在TCP协议中。通过合理的设…

[Postman]接口自动化测试入门

文章大多用作个人学习分享&#xff0c;如果大家觉得有不足或错漏的地方欢迎评论指出或补充 此文章将完整的走一遍一个web页面的接口测试流程 大致路径为&#xff1a; 创建集合->调用接口登录获取token->保存token->带着token去完成其他接口的自动化测试->断言-&g…

✔2848. 与车相交的点

代码实现&#xff1a; 方法一&#xff1a;哈希表 #define fmax(a, b) ((a) > (b) ? (a) : (b))int numberOfPoints(int **nums, int numsSize, int *numsColSize) {int hash[101] {0};int max 0;for (int i 0; i < numsSize; i) {max fmax(max, nums[i][1]);for …

【人工智能】AI创业的前沿思考 | 从垂直领域到通用智能模型AGI的崛起

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

Golang协程泄漏定位和排查

Golang协程泄漏定位和排查 1 场景&#xff1a;无缓冲channel写阻塞2 排查和定位思路2.1 Golang pprof2.2 协程数监控2.3 操作系统内存泄漏 参考 1 场景&#xff1a;无缓冲channel写阻塞 package mainimport ("log""net/http"_ "net/http/pprof"…

PPT中的图形与图片:插入、调整与格式设置技术详解

目录 引言 一、图形与图片的插入 1. 插入图形 2. 插入图片 二、图形与图片的调整 1. 调整大小与位置 2. 裁剪与旋转 3. 图形与图片的合并与组合 三、图片格式与布局设置 1. 图片格式设置 2. 图片布局设置 示例案例&#xff1a;制作产品展示PPT 四、结论 引言 在现…

【OJ刷题】双指针问题4

这里是阿川的博客&#xff0c;祝您变得更强 ✨ 个人主页&#xff1a;在线OJ的阿川 &#x1f496;文章专栏&#xff1a;OJ刷题入门到进阶 &#x1f30f;代码仓库&#xff1a; 写在开头 现在您看到的是我的结论或想法&#xff0c;但在这背后凝结了大量的思考、经验和讨论 目录 1…