浅谈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 如果字典为空
相关推荐
君莫愁。14 分钟前
【Unity】检测鼠标点击位置是否有2D对象
unity·c#·游戏引擎
学步_技术22 分钟前
Python编码系列—Python工厂方法模式:构建灵活对象的秘诀
开发语言·python·工厂方法模式
Deryck_德瑞克39 分钟前
Java集合笔记
java·开发语言·笔记
MengYiKeNan44 分钟前
C++二分函数lower_bound和upper_bound的用法
开发语言·c++·算法
会发paper的学渣1 小时前
python 单例模式实现
开发语言·python·单例模式
Lingbug1 小时前
.Net日志组件之NLog的使用和配置
后端·c#·.net·.netcore
学步_技术1 小时前
Python编码系列—Python桥接模式:连接抽象与实现的桥梁
开发语言·python·桥接模式
柴华松1 小时前
GPU训练代码
开发语言·python
咩咩觉主1 小时前
Unity实战案例全解析:PVZ 植物卡片状态分析
unity·c#·游戏引擎
好兄弟给我起把狙1 小时前
[Golang] Select
开发语言·后端·golang