浅谈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 如果字典为空
相关推荐
GuYue.bing9 分钟前
网络下载ts流媒体
开发语言·python
geovindu11 分钟前
CSharp: Oracle Stored Procedure query table
数据库·oracle·c#·.net
StringerChen16 分钟前
Qt ui提升窗口的头文件找不到
开发语言·qt
数据小爬虫@22 分钟前
如何利用PHP爬虫获取速卖通(AliExpress)商品评论
开发语言·爬虫·php
yngsqq1 小时前
cad c# 二次开发 ——动态加载dll 文件制作(loada netloadx)
c#
java1234_小锋1 小时前
MyBatis如何处理延迟加载?
java·开发语言
FeboReigns1 小时前
C++简明教程(10)(初识类)
c语言·开发语言·c++
学前端的小朱1 小时前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
摇光932 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
沐泽Mu2 小时前
嵌入式学习-QT-Day09
开发语言·qt·学习