浅谈C#之ConcurrentDictionary

一、基本介绍

ConcurrentDictionary 是 .NET Framework 中提供的一个线程安全的字典类,它允许多个线程同时对字典进行读写操作而不需要额外的同步措施。这个类位于 System.Collections.Concurrent 命名空间中。

二、关键特性

线程安全:它内部使用了细粒度的锁定机制,确保在多线程环境中的安全性。

高性能 :相比于其他线程安全的集合,ConcurrentDictionary 在高并发场景下通常提供更好的性能。

灵活的添加和更新 :提供了 TryAddTryUpdateTryRemove 等方法,它们在操作失败时不会抛出异常,而是返回一个布尔值来指示操作是否成功。

支持键和值的泛型:你可以定义任何类型的键和值。

允许空值 :与 Dictionary 不同,ConcurrentDictionary 允许键或值为 null

三、简单示例

cs 复制代码
using System;
using System.Collections.Concurrent;
using System.Threading;

class Program
{
    static void Main()
    {
        ConcurrentDictionary<string, int> concurrentDictionary = new ConcurrentDictionary<string, int>();

        // 添加键值对
        concurrentDictionary.TryAdd("key1", 1);

        // 更新键值对
        concurrentDictionary.TryUpdate("key1", 2, 1);

        // 尝试获取值
        if (concurrentDictionary.TryGetValue("key1", out int value))
        {
            Console.WriteLine($"The value for 'key1' is: {value}");
        }

        // 移除键值对
        concurrentDictionary.TryRemove("key1", out int removedValue);

        // 启动多个线程来操作字典
        Thread thread1 = new Thread(() => UpdateDictionary(concurrentDictionary, "key2", 10));
        Thread thread2 = new Thread(() => UpdateDictionary(concurrentDictionary, "key3", 20));

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        // 输出最终的字典内容
        foreach (var kvp in concurrentDictionary)
        {
            Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
        }
    }

    static void UpdateDictionary(ConcurrentDictionary<string, int> dictionary, string key, int value)
    {
        // 尝试添加或更新字典中的键值对
        dictionary.TryAdd(key, value);
        dictionary.TryUpdate(key, value + 1, value); // 尝试增加值
    }
}

四、详细示例

使用 GetOrAdd 方法

GetOrAdd 方法尝试获取指定键的值。如果找不到该键,则添加一个新的键值对。

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();

int value = dictionary.GetOrAdd("key", k => 10); // 如果 "key" 不存在,则添加键值对 "key" -> 10

使用 AddOrUpdate 方法

AddOrUpdate 方法添加键值对,如果键已存在,则更新值。

cs 复制代码
dictionary.AddOrUpdate("key", 10, (k, existingValue) => existingValue + 10);

使用 ToConcurrency 方法

ToConcurrency 方法允许将现有的 IDictionary 转换为 ConcurrentDictionary

cs 复制代码
var regularDictionary = new Dictionary<string, int>
{
    { "key1", 1 },
    { "key2", 2 }
};

var concurrentDictionary = regularDictionary.ToConcurrency();

使用 AsParallel 方法

AsParallel 方法允许你并行地遍历 ConcurrentDictionary

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();
// 填充字典...

Parallel.ForEach(dictionary.AsParallel(), kvp =>
{
    // 做一些处理,例如更新值
    dictionary.AddOrUpdate(kvp.Key, kvp.Value + 1, (k, v) => v + 1);
});

使用 WithAllLocks 方法

WithAllLocks 方法允许你执行需要多个键同时锁定的操作。

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();
// 填充字典...

dictionary.WithAllLocks(() =>
{
    var total = 0;
    foreach (var kvp in dictionary)
    {
        total += kvp.Value;
    }
    Console.WriteLine($"Total: {total}");
});

使用 TryRemove 方法

TryRemove 方法尝试移除具有特定键的键值对。

cs 复制代码
var result = dictionary.TryRemove("key", out int value);
if (result)
{
    Console.WriteLine($"Removed value: {value}");
}

使用 GetOrAdd 与函数式编程

GetOrAdd 可以与函数式编程结合使用,例如使用 lambda 表达式来计算值。

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();

int value = dictionary.GetOrAdd("key", k => ComputeValue(k)); // ComputeValue 是一个计算值的函数

int ComputeValue(string key)
{
    // 根据 key 计算并返回一个值
    return 42; // 示例值
}

使用 ToDictionary 方法

ToDictionary 方法将 ConcurrentDictionary 转换为 Dictionary

cs 复制代码
var concurrentDictionary = new ConcurrentDictionary<string, int>();
// 填充字典...

var readOnlyDictionary = concurrentDictionary.ToDictionary();

使用 KeysValues 属性

KeysValues 属性允许你获取字典的键集合和值集合。

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();
// 填充字典...

foreach (var key in dictionary.Keys)
{
    Console.WriteLine($"Key: {key}");
}

foreach (var value in dictionary.Values)
{
    Console.WriteLine($"Value: {value}");
}

使用 IsEmpty 属性

IsEmpty 属性可以用来快速检查字典是否为空。

cs 复制代码
var dictionary = new ConcurrentDictionary<string, int>();

bool isEmpty = dictionary.IsEmpty; // true 如果字典为空
相关推荐
CTRA王大大1 小时前
【golang】制作linux环境+golang的Dockerfile | 如何下载golang镜像源
linux·开发语言·docker·golang
zhangfeng11332 小时前
以下是基于图论的归一化切割(Normalized Cut)图像分割工具的完整实现,结合Tkinter界面设计及Python代码示
开发语言·python·图论
还梦呦3 小时前
2025年09月计算机二级Java选择题每日一练——第五期
java·开发语言·计算机二级
鱼鱼说测试3 小时前
postman接口自动化测试
开发语言·lua
從南走到北4 小时前
JAVA国际版东郊到家同城按摩服务美容美发私教到店服务系统源码支持Android+IOS+H5
android·java·开发语言·ios·微信·微信小程序·小程序
_不会dp不改名_4 小时前
C++ 20: Concepts 与Requires
开发语言·c++20
韭菜钟4 小时前
Qt从qmake迁移到cmake的记录
开发语言·qt
少陵野小Tommy5 小时前
Python能用古诗词数据库做什么7:根据标题、诗句查找诗歌
开发语言·数据库·python
长城20245 小时前
PHP如何使用JpGraph生成3D饼形图?
开发语言·php·jpgraph·3d饼形图
BIGFISH20195 小时前
上下相机引导贴合的标定(绝对坐标方式)
c#