
在多线程编程中,线程安全的数据结构是确保数据一致性和避免竞争条件的关键。.NET 提供了多种线程安全的数据结构,适用于不同的场景,本篇将介绍它们的简单使用以及在 .NET Core 和 .NET Framework 中的可用性。
ConcurrentQueue 是一个线程安全的先进先出 (FIFO) 队列。它允许多个线程同时进行入队和出队操作,而不会导致数据不一致。
适用场景
优点
Enqueue
和TryDequeue
可用性
示例代码
using System.Collections.Concurrent; var queue = new ConcurrentQueue<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生产者任务 var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { queue.Enqueue(i); Console.WriteLine($"Enqueued {i}"); Thread.Sleep(100); // 模拟生产延迟 } }, token); // 消费者任务 var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (queue.TryDequeue(out int result)) { Console.WriteLine($"Dequeued {result}"); } Thread.Sleep(50); // 模拟消费延迟 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消费者任务 await consumer;
ConcurrentStack 是一个线程安全的后进先出 (LIFO) 堆栈。它允许多个线程同时进行入栈和出栈操作。
适用场景
优点
Push
和TryPop
可用性
示例代码
using System.Collections.Concurrent; var stack = new ConcurrentStack<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生产者任务 var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { stack.Push(i); Console.WriteLine($"Pushed {i}"); Thread.Sleep(100); // 模拟生产延迟 } }, token); // 消费者任务 var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (stack.TryPop(out int result)) { Console.WriteLine($"Popped {result}"); } Thread.Sleep(50); // 模拟消费延迟 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消费者任务 await consumer;
ConcurrentBag 是一个线程安全的无序集合,适用于频繁添加和删除元素的场景。
适用场景
优点
可用性
示例代码
using System.Collections.Concurrent; var bag = new ConcurrentBag<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生产者任务 var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { bag.Add(i); Console.WriteLine($"Added {i}"); Thread.Sleep(100); // 模拟生产延迟 } }, token); // 消费者任务 var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (bag.TryTake(out int result)) { Console.WriteLine($"Took {result}"); } Thread.Sleep(50); // 模拟消费延迟 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消费者任务 await consumer;
ConcurrentDictionary<TKey, TValue> 是一个线程安全的键值对集合,类似于 Dictionary<TKey, TValue>。
适用场景
优点
AddOrUpdate
和GetOrAdd
,确保数据一致性可用性
示例代码
using System.Collections.Concurrent; var dictionary = new ConcurrentDictionary<int, string>(); // 添加元素 var addTask = Task.Run(() => { for (int i = 0; i < 10; i++) { dictionary.TryAdd(i, $"value{i}"); Console.WriteLine($"Added key {i} with value value{i}"); } }); // 更新元素 var updateTask = Task.Run(() => { for (int i = 0; i < 10; i++) { var ii = i; dictionary.AddOrUpdate(i, $"new_value{i}", (key, oldValue) => $"new_value{ii}"); Console.WriteLine($"Updated key {i} with value new_value{i}"); } }); // 读取元素 var readTask = Task.Run(() => { foreach (var key in dictionary.Keys) { if (dictionary.TryGetValue(key, out string? value)) { Console.WriteLine($"Key {key} has value {value}"); } } }); await Task.WhenAll(addTask, updateTask, readTask);
BlockingCollection 提供线程安全的添加和移除操作,并支持阻塞和限界功能。可以与ConcurrentQueue<T>
, ConcurrentStack<T>
, ConcurrentBag<T>
等一起使用。
适用场景
优点
ConcurrentQueue<T>
可用性
示例代码
using System.Collections.Concurrent; var collection = new BlockingCollection<int>(boundedCapacity: 5); var cts = new CancellationTokenSource(); var token = cts.Token; // 生产者任务 var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { collection.Add(i); Console.WriteLine($"Added {i}"); Thread.Sleep(100); // 模拟生产延迟 } collection.CompleteAdding(); }, token); // 消费者任务 var consumer = Task.Run(() => { foreach (var item in collection.GetConsumingEnumerable(token)) { Console.WriteLine($"Consumed {item}"); Thread.Sleep(50); // 模拟消费延迟 } }, token); await Task.WhenAll(producer, consumer);
ImmutableList 是线程安全的,因为所有修改操作都会返回一个新的集合实例。
适用场景
优点
可用性
System.Collections.Immutable
NuGet 包)System.Collections.Immutable
NuGet 包)示例代码
var list = ImmutableList.Create(1, 2, 3); var newList = list.Add(4); Console.WriteLine(string.Join(", ", newList)); // 输出 1, 2, 3, 4
SynchronizedCollection 是一个线程安全的集合,适用于需要同步访问的场景。
适用场景
优点
Add
和Remove
可用性
示例代码
var collection = new SynchronizedCollection<int>(); collection.Add(1); collection.Add(2); foreach (var item in collection) { Console.WriteLine(item); // 输出 1 和 2 }
SynchronizedReadOnlyCollection 是一个线程安全的只
读集合。
适用场景
优点
Contains
和CopyTo
可用性
示例代码
var list = new List<int> { 1, 2, 3 }; var readOnlyCollection = new SynchronizedReadOnlyCollection<int>(list); foreach (var item in readOnlyCollection) { Console.WriteLine(item); // 输出 1, 2, 3 }
SynchronizedKeyedCollection<K, T> 是一个线程安全的键控集合。
使用场景
优点
可用性
示例代码
public class MyItem { public int Id { get; set; } public string Name { get; set; } } var collection = new SynchronizedKeyedCollection<int, MyItem>(item => item.Id); collection.Add(new MyItem { Id = 1, Name = "Item1" }); collection.Add(new MyItem { Id = 2, Name = "Item2" }); foreach (var item in collection) { Console.WriteLine(item.Name); // 输出 Item1 和 Item2 }
到此这篇关于.NET 中的线程安全数据结构的文章就介绍到这了,更多相关.NET线程安全数据结构内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!