C#开发——ConcurrentDictionary集合

        ConcurrentDictionary<TKey, TValue>   是 C# 中一个专为多线程场景设计的线程安全字典集合,位于   System.Collections.Concurrent   命名空间中。它允许多个线程同时对字典进行读写操作,而无需额外的同步措施。

一、集合特征

此集合有如下特征:

1. 线程安全:

•   ConcurrentDictionary   内部使用了细粒度的锁定机制(如分段锁)或无锁技术,确保在多线程环境中的操作安全。

• 绝大多数操作(如   TryAdd  、  TryUpdate  、  TryRemove  )都是线程安全的。

2. 高性能:

• 由于采用了细粒度锁定或无锁技术,  ConcurrentDictionary   在高并发场景下通常比普通字典(如   Dictionary<TKey, TValue>  )具有更好的性能。

3. 灵活的操作方法:

• 提供了多种线程安全的方法,如   TryAdd  、  TryUpdate  、  TryRemove   和   GetOrAdd   等。这些方法在操作失败时不会抛出异常,而是返回一个布尔值来指示操作是否成功。

• 特别需要注意的是,  AddOrUpdate   和   GetOrAdd   方法中涉及委托的部分并不是完全原子性的,需要开发者特别注意。

4. 允许空值:• 与普通   Dictionary   不同,  ConcurrentDictionary   允许键或值为   null  。

        使用示例以下是一个简单的   ConcurrentDictionary   使用示例:

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;class Program
{static void Main(){// 创建一个线程安全的 ConcurrentDictionary 实例ConcurrentDictionary<int, string> concurrentDictionary = new ConcurrentDictionary<int, string>();// 使用 TryAdd 方法添加键值对concurrentDictionary.TryAdd(1, "one");concurrentDictionary.TryAdd(2, "two");// 使用 TryGetValue 方法获取值if (concurrentDictionary.TryGetValue(1, out string value)){Console.WriteLine($"Value for key 1: {value}");}// 使用 AddOrUpdate 方法更新或添加键值对concurrentDictionary.AddOrUpdate(1, "new one", (key, oldValue) => "updated one");// 使用 TryRemove 方法移除键值对concurrentDictionary.TryRemove(2, out _);// 在多线程环境中操作 ConcurrentDictionaryParallel.For(3, 10, i =>{concurrentDictionary.TryAdd(i, i.ToString());});// 遍历并输出 ConcurrentDictionary 中的所有元素foreach (var item in concurrentDictionary){Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");}}
}

二、适用场景

• 多线程数据共享:当多个线程需要同时访问和修改同一个字典时,  ConcurrentDictionary   是最合适的选择。

• 高并发场景:在需要高性能并发访问的场景中,  ConcurrentDictionary   的细粒度锁定机制可以显著减少锁竞争。注意事项• 委托方法的线程安全性:  AddOrUpdate   和   GetOrAdd   方法中涉及委托的部分并不是完全原子性的,因此需要开发者确保委托操作的线程安全性。

• 性能优化:虽然   ConcurrentDictionary   本身性能较高,但在极端高并发场景下,仍需根据实际需求进行性能测试和优化。

总之,  ConcurrentDictionary   是一个强大的线程安全字典集合,适用于多线程和高并发场景,能够有效解决普通字典在多线程环境下的线程安全问题。

三、高性能

  ConcurrentDictionary<TKey, TValue>   的高性能主要体现在以下几个方面:

1. 细粒度锁定与无锁算法 

        ConcurrentDictionary   内部采用了细粒度锁定(分段锁)或无锁算法(Lock-free),这使得多个线程可以同时对字典进行操作,而不会出现严重的竞争条件。例如,它使用了 CAS(Compare and Swap)操作来确保线程安全,这种无锁机制减少了线程间的同步开销。

2. 动态扩容

        ConcurrentDictionary   支持动态扩容,能够根据实际负载自动调整内部数据结构的大小。这种动态调整能力使得它能够适应不同的并发场景,避免因固定容量导致的性能瓶颈。

3. 高效的哈希表实现

        ConcurrentDictionary   内部基于哈希表实现,使用散列函数将键映射到存储位置,并通过链表或红黑树处理冲突。这种数据结构支持常数时间复杂度(O(1))的添加、查找和修改操作,从而提高了整体性能。

4. 适用于多生产者和多消费者场景

        ConcurrentDictionary   的设计目标是在多生产者和多消费者环境中提供高效的并发访问。它允许多个线程同时对字典进行读写操作,而无需额外的同步机制。

5. 减少锁的开销

        与传统的线程安全集合(如通过   lock   实现的同步机制)相比,  ConcurrentDictionary   通过优化的并发算法减少了锁的使用频率和范围。这种设计不仅提高了性能,还降低了死锁的风险。

6. 灵活的操作方法

        ConcurrentDictionary   提供了多种线程安全的操作方法,如   TryAdd  、  TryUpdate   和   TryRemove  ,这些方法在操作失败时不会抛出异常,而是返回布尔值,从而避免了异常处理的开销。

        总结  ConcurrentDictionary   的高性能主要得益于其细粒度锁定或无锁算法、动态扩容能力、高效的哈希表实现以及对多生产者和多消费者场景的优化。这些特性使其在高并发场景下表现出色,能够显著提高多线程应用程序的性能。

四、常用属性

Count:获取字典中键值对的数量。

IsEmpty:判断字典是否为空。

Keys:获取字典中所有键的集合(返回   IEnumerable<TKey>  )。

Values:获取字典中所有值的集合(返回   IEnumerable<TValue>  )。

实例代码:

var dict = new ConcurrentDictionary<int, string>();
dict.TryAdd(1, "one");
dict.TryAdd(2, "two");
//Count 属性
Console.WriteLine(dict.Count); // 输出:2var dict = new ConcurrentDictionary<int, string>();
//IsEmpty 属性
Console.WriteLine(dict.IsEmpty); // 输出:True
dict.TryAdd(1, "one");
Console.WriteLine(dict.IsEmpty); // 输出:Falsevar dict = new ConcurrentDictionary<int, string>
{{1, "one"},{2, "two"}
};
//Keys 属性
foreach (var key in dict.Keys)
{Console.WriteLine(key); // 输出:1, 2
}var dict = new ConcurrentDictionary<int, string>
{{1, "one"},{2, "two"}
};
//Values 属性
foreach (var value in dict.Values)
{Console.WriteLine(value); // 输出:"one", "two"
}var dict = new ConcurrentDictionary<int, string>();
bool added = dict.TryAdd(1, "one");
Console.WriteLine(added); // 输出:True
added = dict.TryAdd(1, "one");
Console.WriteLine(added); // 输出:False

五、常用方法

TryAdd(TKey key, TValue value):尝试将键值对添加到字典中。如果键已存在,则返回   false  。

TryUpdate(TKey key, TValue newValue, TValue comparisonValue):尝试更新指定键的值。只有当当前值等于   comparisonValue   时,才会更新为   newValue 。

TryRemove(TKey key, out TValue value):尝试从字典中移除指定键的键值对,并返回其值。

 GetOrAdd(TKey key, TValue value):如果字典中不存在指定键,则添加键值对并返回值;如果已存在,则返回已有的值。

GetOrAdd(TKey key, Func<TKey, TValue> valueFactory):如果字典中不存在指定键,则通过   valueFactory   动态生成值并添加到字典中。

AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory):如果键不存在,则添加   addValue  ;如果键已存在,则通过   updateValueFactory   更新值。

ContainsKey(TKey key):判断字典中是否包含指定键。

Clear():清空字典中的所有键值对。

参考代码:

var dict = new ConcurrentDictionary<int, string>();
//TryAdd()方法
bool added = dict.TryAdd(1, "one");
Console.WriteLine(added); // 输出:True
added = dict.TryAdd(1, "one");
Console.WriteLine(added); // 输出:Falsevar dict = new ConcurrentDictionary<int, string>
{{1, "one"}
};
//TryUpdate()方法
bool updated = dict.TryUpdate(1, "new one", "one");
Console.WriteLine(updated); // 输出:True
updated = dict.TryUpdate(1, "updated one", "old one");
Console.WriteLine(updated); // 输出:Falsevar dict = new ConcurrentDictionary<int, string>
{{1, "one"}
};
//TryRemove()方法
bool removed = dict.TryRemove(1, out string value);
Console.WriteLine(removed); // 输出:True
Console.WriteLine(value); // 输出:"one"var dict = new ConcurrentDictionary<int, string>();
//GetOrAdd()方法
string value = dict.GetOrAdd(1, "one");
Console.WriteLine(value); // 输出:"one"
value = dict.GetOrAdd(1, "new one");
Console.WriteLine(value); // 输出:"one"(未更新)var dict = new ConcurrentDictionary<int, string>();
//GetOrAdd()方法
string value = dict.GetOrAdd(1, key => $"Value for {key}");
Console.WriteLine(value); // 输出:"Value for 1"var dict = new ConcurrentDictionary<int, string>();
//AddOrUpdate()方法
dict.AddOrUpdate(1, "one", (key, oldValue) => $"Updated {oldValue}");
Console.WriteLine(dict[1]); // 输出:"one"
dict.AddOrUpdate(1, "new one", (key, oldValue) => $"Updated {oldValue}");
Console.WriteLine(dict[1]); // 输出:"Updated one"var dict = new ConcurrentDictionary<int, string>
{{1, "one"}
};
//ContainsKey()方法
bool contains = dict.ContainsKey(1);
Console.WriteLine(contains); // 输出:Truevar dict = new ConcurrentDictionary<int, string>
{{1, "one"}
};
//Clear()方法
dict.Clear();
Console.WriteLine(dict.Count); // 输出:0

其他方法

GetEnumerator():返回一个枚举器,用于遍历字典中的键值对。

ToDictionary():将ConcurrentDictionary转换为普通的Dictionary<TKey, TValue>。

总结

ConcurrentDictionary<TKey, TValue> 提供了丰富的线程安全方法,适用于多线程环境。常用的方法如   TryAdd、TryUpdate、TryRemove、GetOrAdd和AddOrUpdate等,能够灵活地处理并发操作,同时避免了传统字典在多线程场景下的线程安全问题。

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

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

相关文章

Unity百游修炼(2)——Brick_Breaker详细制作全流程

一、项目简介 Brick Breaker 是一款经典的打砖块游戏&#xff0c;本次案例将使用 Unity 引擎来实现该游戏的核心功能。 游戏画面如下&#xff1a; Brick_ breaker 二、项目结构概览和前期准备 &#xff08;1&#xff09;在 Unity 项目视图中&#xff0c;我们可以看到几个重要…

KubeSphere平台安装

KubeSphere简介 KubeSphere 是一款功能强大的容器管理平台&#xff0c;以下是其简介&#xff1a; 1&#xff09;基本信息 开源项目&#xff1a;基于 Apache-2.0 授权协议开源&#xff0c;由 Google Go、Groovy、HTML/CSS 和 Shell 等多种编程语言开发。基础架构&#xff1a;…

UE5销毁Actor,移动Actor,简单的空气墙的制作

1.销毁Actor 1.Actor中存在Destory()函数和Destoryed()函数 Destory()函数是成员函数&#xff0c;它会立即标记 Actor 为销毁状态&#xff0c;并且会从场景中移除该 Actor。它会触发生命周期中的销毁过程&#xff0c;调用 Destroy() 后&#xff0c;Actor 立即进入销毁过程。具体…

Hadoop 基础原理

Hadoop 基础原理 基本介绍Hadoop 的必要性Hadoop 核心组件Hadoop 生态系统中的附加组件 HDFSHDFS 集群架构HDFS 读写流程HDFS 写流程HDFS 读流程 NameNode 持久化机制 MapReduce底层原理示例 Hadoop 是一个由 Apache 基金会开发的分布式系统基础架构&#xff0c;主要解决海量数…

Linux编辑器

1.三种模式 2.图例 3.wq 4.光标的使用

2.24DFS和BFS刷题

洛谷P2895&#xff1a;用BFS走出危险区域&#xff0c;危险区域存在时间&#xff0c;我们用ma记录最快变成危险区域的时间&#xff0c; 然后每次枚举时间1然后跟ma数组比较看能不能走&#xff0c;然后时间复杂度为O(305^2)。 #include<iostream> #include<cstring>…

TMDS视频编解码算法

因为使用的是DDR进行传输&#xff0c;即双倍频率采样&#xff0c;故时钟只用是并行数据数据的5倍&#xff0c;而不是10倍。 TMDS算法流程&#xff1a; 视频编码TMDS算法流程实现&#xff1a; timescale 1 ps / 1ps //DVI编码通常用于视频传输&#xff0c;将并行数据转换为适合…

C++中tuple的用法

C中tuple的用法 在C中&#xff0c;std::tuple 是一个模板类&#xff0c;用于存储一组不同类型的值。它类似于 Python 中的元组&#xff0c;但具有更强大的功能&#xff0c;例如支持不同类型的元素和更复杂的操作。std::tuple 是 C11 标准引入的&#xff0c;位于 <tuple>…

计算机网络————(一)HTTP讲解

基础内容分类 从TCP/IP协议栈为依托&#xff0c;由上至下、从应用层到基础设施介绍协议。 1.应用层&#xff1a; HTTP/1.1 Websocket HTTP/2.0 2.应用层的安全基础设施 LTS/SSL 3.传输层 TCP 4.网络层及数据链路层 IP层和以太网 HTTP协议 网络页面形成基本 流程&#xff1a…

【网络编程】广播和组播

数据包发送方式只有一个接受方&#xff0c;称为单播。如果同时发给局域网中的所有主机&#xff0c;称为广播。只有用户数据报(使用UDP协议)套接字才能广播&#xff1a; 广播地址以192.168.1.0 (255.255.255.0) 网段为例&#xff0c;最大的主机地址192.168.1.255代表该网段的广…

小程序如何实现跨页面通信

前言 最近有很多同学问&#xff0c;小程序里面如何进行跨页面通信。看了下之前的老代码&#xff0c;基本都是基于onShow或者localStorage。虽然可以实现&#xff0c;但是并不怎么优雅。 今天就来聊一聊&#xff0c;小程序的跨页面通信的几种实现方案。或许会有你想要的方案&a…

【工具】win-画图 保留图片信息并仅改变图片比例的工具

Windows 系统自带的“画图”工具 Windows 系统自带的“画图”&#xff08;Paint&#xff09;工具可以进行简单的图片编辑&#xff0c;包括调整图片大小和比例。 使用方法&#xff1a; 打开“画图”工具&#xff08;可以通过在开始菜单中搜索“画图”或“Paint”&#xff09;。…

如何编辑autodl中以.bashrc结尾的隐藏文件

在nnunet的运行过程中遇到了设置环境变量的问题。之前没有接触过linux系统&#xff0c;但是autodl里面默认是linux系统。.bashrc 是一个在 Bash shell 启动时执行的脚本文件&#xff0c;常用于设置环境变量、定义别名、加载函数等&#xff0c;用户可以通过编辑这个文件来定制自…

实验3 知识表示与推理

实验3 知识表示与推理 一、实验目的 &#xff08;1&#xff09;掌握知识和知识表示的基本概念&#xff0c;理解其在AI中的深刻含义与意义&#xff1b; &#xff08;2&#xff09;熟悉AI中常用的知识表示方法的优缺点及其应用场景&#xff1b; &#xff08;3&#xff09;掌握产…

在 M1 Mac 上解锁 TensorFlow GPU 加速:从环境搭建到实战验证

在 M1 Mac 上解锁 TensorFlow GPU 加速&#xff1a;从环境搭建到实战验证 前言&#xff1a;苹果芯片的深度学习新纪元 随着 Apple Silicon 芯片的普及&#xff0c;M1/M2/M3 系列 Mac 已成为移动端深度学习开发的新选择。本文将以 TensorFlow 2.x 为例&#xff0c;手把手教你如…

Python 数据分析概述 ①

一文读懂Python数据分析&#xff1a;从基础到实践全攻略 在当今数字化浪潮中&#xff0c;数据分析已然成为解锁海量数据价值的关键钥匙&#xff0c;而Python凭借其独特优势&#xff0c;在数据分析领域大放异彩。今天&#xff0c;咱们就结合教学PPT内容&#xff0c;深入探索Pyt…

【Gin-Web】Bluebell社区项目梳理6:限流策略-漏桶与令牌桶

本文目录 一、限流二、漏桶三、令牌桶算法四、Gin框架中实现令牌桶限流 一、限流 限流又称为流量控制&#xff0c;也就是流控&#xff0c;通常是指限制到达系统的并发请求数。 限流虽然会影响部分用户的使用体验&#xff0c;但是能一定程度上保证系统的稳定性&#xff0c;不至…

Linux高并发服务器开发 第十九天(线程 进程)

目录 1.进程组和会话 2.守护进程 2.1守护进程daemon概念 2.2创建守护进程 3.线程 3.1线程的概念 3.2线程内核三级映射 3.3线程共享 3.4线程优缺点 4.线程控制原语 4.1获取线程id 4.2创建线程 4.3循环创建N个子线 4.4子线程传参地址&#xff0c;错误示例 4.5线程…

软件工程和系统分析与设计

软件工程 1、软件危机 2、软件过程模型 2.1 瀑布模型 2.2原型模型 2.3螺旋模型 2.4敏捷模型 2.5软件统一过程 3、软件能力成熟度模型 CMM 4、软件能力成熟度模型集成 CMMI 系统分析与设计 1、结构化方法SASD 1.1结构化分析 DFD 1.2结构化设计 SD-是一种面向数据流的设计…

Qt/C++面试【速通笔记一】

Qt 信号与槽机制 什么是信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;&#xff1f; 在Qt中&#xff0c;信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;是实现对象之间通信的一种机制。信号是对象在某些事件发生时发出的通知&…