浅谈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 如果字典为空
相关推荐
萧鼎1 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸1 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农1 小时前
Python 继承、多态、封装、抽象
开发语言·python
^velpro^1 小时前
数据库连接池的创建
java·开发语言·数据库
秋の花1 小时前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端1 小时前
第六章 7.0 LinkList
java·开发语言·网络
可峰科技1 小时前
斗破QT编程入门系列之二:认识Qt:编写一个HelloWorld程序(四星斗师)
开发语言·qt
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
面试鸭1 小时前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
小白学大数据1 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫