一、基本介绍
ConcurrentDictionary
是 .NET Framework 中提供的一个线程安全的字典类,它允许多个线程同时对字典进行读写操作而不需要额外的同步措施。这个类位于 System.Collections.Concurrent
命名空间中。
二、关键特性
线程安全:它内部使用了细粒度的锁定机制,确保在多线程环境中的安全性。
高性能:相比于其他线程安全的集合,ConcurrentDictionary
在高并发场景下通常提供更好的性能。
灵活的添加和更新:提供了 TryAdd
、TryUpdate
和 TryRemove
等方法,它们在操作失败时不会抛出异常,而是返回一个布尔值来指示操作是否成功。
支持键和值的泛型:你可以定义任何类型的键和值。
允许空值:与 Dictionary
不同,ConcurrentDictionary
允许键或值为 null
。
三、简单示例
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
方法尝试获取指定键的值。如果找不到该键,则添加一个新的键值对。
var dictionary = new ConcurrentDictionary<string, int>();
int value = dictionary.GetOrAdd("key", k => 10); // 如果 "key" 不存在,则添加键值对 "key" -> 10
使用 AddOrUpdate
方法
AddOrUpdate
方法添加键值对,如果键已存在,则更新值。
dictionary.AddOrUpdate("key", 10, (k, existingValue) => existingValue + 10);
使用 ToConcurrency
方法
ToConcurrency
方法允许将现有的 IDictionary
转换为 ConcurrentDictionary
。
var regularDictionary = new Dictionary<string, int>
{
{ "key1", 1 },
{ "key2", 2 }
};
var concurrentDictionary = regularDictionary.ToConcurrency();
使用 AsParallel
方法
AsParallel
方法允许你并行地遍历 ConcurrentDictionary
。
var dictionary = new ConcurrentDictionary<string, int>();
// 填充字典...
Parallel.ForEach(dictionary.AsParallel(), kvp =>
{
// 做一些处理,例如更新值
dictionary.AddOrUpdate(kvp.Key, kvp.Value + 1, (k, v) => v + 1);
});
使用 WithAllLocks
方法
WithAllLocks
方法允许你执行需要多个键同时锁定的操作。
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
方法尝试移除具有特定键的键值对。
var result = dictionary.TryRemove("key", out int value);
if (result)
{
Console.WriteLine($"Removed value: {value}");
}
使用 GetOrAdd
与函数式编程
GetOrAdd
可以与函数式编程结合使用,例如使用 lambda 表达式来计算值。
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
。
var concurrentDictionary = new ConcurrentDictionary<string, int>();
// 填充字典...
var readOnlyDictionary = concurrentDictionary.ToDictionary();
使用 Keys
、Values
属性
Keys
和 Values
属性允许你获取字典的键集合和值集合。
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
属性可以用来快速检查字典是否为空。
var dictionary = new ConcurrentDictionary<string, int>();
bool isEmpty = dictionary.IsEmpty; // true 如果字典为空