news 2026/4/25 19:06:08

System.Collections.Concurrent 命名空间提供了专门为多线程并发场景设计的并发集合,这些集合内部使用原子操作(如 Interlocked)、锁或其他同步机制,确保线程安全

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
System.Collections.Concurrent 命名空间提供了专门为多线程并发场景设计的并发集合,这些集合内部使用原子操作(如 Interlocked)、锁或其他同步机制,确保线程安全

在 C# 中,System.Collections.Concurrent 命名空间提供了专门为多线程并发场景设计的并发集合,这些集合内部使用原子操作(如 Interlocked)、锁或其他同步机制,确保线程安全,同时尽量减少性能开销。

相比手动使用 Interlocked 或 lock,并发集合提供了更高级的抽象,适合复杂场景,如多线程数据共享、任务队列等。

以下是对 C# 并发集合的详细解析,包括其核心类、实现机制、实际应用场景和具体代码示例。


1. 并发集合概述System.Collections.Concurrent 命名空间中的并发集合设计目标是:

  • 线程安全:无需显式加锁即可在多线程环境中安全使用。
  • 高性能:通过细粒度锁或无锁技术(如原子操作)减少同步开销。
  • 易用性:提供直观的 API,简化并发编程。

主要的并发集合包括:

  • ConcurrentDictionary<TKey, TValue>:线程安全的键值对集合,支持并发读写。
  • ConcurrentQueue<T>:线程安全的先进先出(FIFO)队列。
  • ConcurrentStack<T>:线程安全的后进先出(LIFO)栈。
  • ConcurrentBag<T>:线程安全的无序集合,适合高并发添加和遍历。
  • BlockingCollection<T>:阻塞式集合,支持生产者-消费者模式。

2. 各并发集合的细节以下是对每个并发集合的详细说明,包括其实现机制、适用场景和关键方法。

2.1 ConcurrentDictionary<TKey, TValue>

  • 功能:线程安全的键值对集合,允许多线程同时添加、移除、查询和更新键值对。
  • 内部实现:
    • 使用细粒度锁(分段锁,lock striping)分片管理键值对,减少锁竞争。
    • 部分操作(如 TryGetValue)可能使用原子操作(如 Interlocked)优化。
  • 关键方法:
    • TryAdd(TKey, TValue):尝试添加键值对,若键已存在则返回 false。
    • TryGetValue(TKey, out TValue):尝试获取指定键的值。
    • TryUpdate(TKey, TValue, TValue):原子性地更新键的值(需匹配旧值)。
    • TryRemove(TKey, out TValue):尝试移除键值对并返回移除的值。
    • AddOrUpdate(TKey, TValue, Func<TKey, TValue, TValue>):添加或更新键值对。
    • GetOrAdd(TKey, TValue):获取键的值,若不存在则添加。
  • 适用场景:
    • 缓存系统(如存储用户会话数据)。
    • 共享配置或状态。
    • 动态更新的键值对存储。
  • 注意事项:
    • 性能优于锁保护的 Dictionary,但仍可能因锁竞争影响高并发场景。
    • 枚举操作(如 foreach)获取的是某一时刻的快照,可能不反映最新状态。

2.2 ConcurrentQueue<T>

  • 功能:线程安全的 FIFO 队列,支持多线程入队和出队。
  • 内部实现:
    • 使用无锁技术(如 Interlocked.CompareExchange)实现入队和出队。
    • 基于链表结构,动态扩展。
  • 关键方法:
    • Enqueue(T):将元素添加到队列尾部。
    • TryDequeue(out T):尝试从队列头部移除并返回元素。
    • TryPeek(out T):尝试查看队列头部元素但不移除。
    • Count:获取队列元素数量(可能不精确,因并发修改)。
  • 适用场景:
    • 任务队列(如线程池任务调度)。
    • 生产者-消费者模式。
  • 注意事项:
    • 无锁实现使其高效,但高并发下可能因重试(如 CAS 失败)影响性能。
    • Count 属性可能因并发操作返回不准确的结果。

2.3 ConcurrentStack<T>

  • 功能:线程安全的 LIFO 栈,支持多线程压栈和弹栈。
  • 内部实现:
    • 类似 ConcurrentQueue,使用无锁技术(如 Interlocked)实现。
    • 基于链表结构。
  • 关键方法:
    • Push(T):将元素压入栈顶。
    • TryPop(out T):尝试从栈顶弹出元素。
    • TryPeek(out T):尝试查看栈顶元素但不弹出。
    • PushRange(T[]) / TryPopRange(T[]):批量压入或弹出元素。
  • 适用场景:
    • 后进先出场景(如撤销/重做操作)。
    • 线程安全的堆栈管理。
  • 注意事项:
    • 批量操作(如 PushRange)可能使用锁,性能稍低于单元素操作。
    • 枚举操作获取快照,可能不反映最新状态。

2.4 ConcurrentBag<T>

  • 功能:线程安全的无序集合,优化了高并发添加和遍历。
  • 内部实现:
    • 每个线程维护自己的局部列表(thread-local list),减少竞争。
    • 使用 Interlocked 确保跨线程操作的原子性。
  • 关键方法:
    • Add(T):添加元素到集合。
    • TryTake(out T):尝试移除并返回一个元素(无序)。
    • TryPeek(out T):尝试查看一个元素但不移除。
  • 适用场景:
    • 高并发添加和移除场景(如日志收集)。
    • 不关心元素顺序的集合。
  • 注意事项:
    • 元素顺序不可预测,适合无序场景。
    • 性能优于其他集合在高并发添加场景,但移除操作可能较慢。

2.5 BlockingCollection<T>

  • 功能:线程安全的阻塞集合,支持生产者-消费者模式,提供阻塞和限界功能。
  • 内部实现:
    • 基于其他并发集合(如 ConcurrentQueue)实现。
    • 使用锁和信号量(如 SemaphoreSlim)实现阻塞和限界。
  • 关键方法:
    • Add(T):添加元素,若集合已满则阻塞。
    • Take():移除并返回元素,若集合为空则阻塞。
    • TryAdd(T, TimeSpan) / TryTake(out T, TimeSpan):尝试添加或移除,带超时。
    • CompleteAdding():标记集合不再接受新元素。
  • 适用场景:
    • 生产者-消费者模式(如任务管道)。
    • 限界队列(如控制内存使用)。
  • 注意事项:
    • 可设置最大容量(bounded capacity),防止无限增长。
    • 枚举操作(如 GetConsumingEnumerable)适合消费者线程。

3. 并发集合的内部机制

  • 原子操作:ConcurrentQueue 和 ConcurrentStack 广泛使用 Interlocked 实现无锁操作(如 CAS),提高性能。
  • 细粒度锁:ConcurrentDictionary 使用分段锁,减少锁竞争。
  • 线程局部存储:ConcurrentBag 为每个线程维护独立列表,减少跨线程竞争。
  • 内存屏障:并发集合内部隐式使用内存屏障(如通过 Interlocked 或 Volatile),确保内存操作的可见性。
  • 异常安全:并发集合方法(如 TryAdd、TryDequeue)返回布尔值,避免抛出异常,提高鲁棒性。

4. 实际应用场景与代码示例以下是并发集合在 C# 中的典型应用场景和具体实现。

4.1 ConcurrentDictionary:线程安全缓存

  • 场景:实现一个线程安全的内存缓存,存储用户数据。
  • 实现:
using System; using System.Collections.Concurrent; using System.Threading.Tasks; class Cache { private readonly ConcurrentDictionary<string, string> _cache = new ConcurrentDictionary<string, string>(); public void AddOrUpdate(string key, string value) { _cache.AddOrUpdate(key, value, (k, oldValue) => value); Console.WriteLine($"Cached {key}: {value}"); } public bool TryGet(string key, out string value) { return _cache.TryGetValue(key, out value); } } class Program { static async Task Main() { var cache = new Cache(); var tasks = new Task[3]; tasks[0] = Task.Run(() => cache.AddOrUpdate("user1", "Alice")); tasks[1] = Task.Run(() => cache.AddOrUpdate("user2", "Bob")); tasks[2] = Task.Run(() => { if (cache.TryGet("user1", out string value)) Console.WriteLine($"Retrieved: user1 = {value}"); }); await Task.WhenAll(tasks); } }
  • 说明:ConcurrentDictionary 确保多线程安全地添加和查询缓存数据。

4.2 ConcurrentQueue:生产者-消费者模式

  • 场景:实现任务队列,生产者添加任务,消费者处理任务。
  • 实现:
using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; class Program { static ConcurrentQueue<int> queue = new ConcurrentQueue<int>(); static CancellationTokenSource cts = new CancellationTokenSource(); static async Task Producer() { for (int i = 1; i <= 5; i++) { queue.Enqueue(i); Console.WriteLine($"Produced: {i}"); await Task.Delay(500); } cts.Cancel(); } static async Task Consumer() { while (!cts.Token.IsCancellationRequested) { if (queue.TryDequeue(out int item)) { Console.WriteLine($"Consumed: {item}"); } await Task.Delay(1000); } } static async Task Main() { var producer = Task.Run(Producer); var consumer = Task.Run(Consumer); await Task.WhenAll(producer, consumer); } }
  • 说明:ConcurrentQueue 提供线程安全的入队和出队操作,适合生产者-消费者模式。

4.3 ConcurrentStack:撤销操作

  • 场景:实现线程安全的撤销堆栈。
  • 实现:
using System; using System.Collections.Concurrent; using System.Threading.Tasks; class UndoStack { private readonly ConcurrentStack<string> _actions = new ConcurrentStack<string>(); public void RecordAction(string action) { _actions.Push(action); Console.WriteLine($"Recorded: {action}"); } public bool TryUndo(out string action) { return _actions.TryPop(out action); } } class Program { static async Task Main() { var undoStack = new UndoStack(); var tasks = new Task[4]; tasks[0] = Task.Run(() => undoStack.RecordAction("Action1")); tasks[1] = Task.Run(() => undoStack.RecordAction("Action2")); tasks[2] = Task.Run(() => { if (undoStack.TryUndo(out string action)) Console.WriteLine($"Undone: {action}"); }); tasks[3] = Task.Run(() => { if (undoStack.TryUndo(out string action)) Console.WriteLine($"Undone: {action}"); }); await Task.WhenAll(tasks); } }
  • 说明:ConcurrentStack 确保多线程安全地记录和撤销操作。

4.4 ConcurrentBag:日志收集

  • 场景:多线程收集日志条目。
  • 实现:

csharp

using System; using System.Collections.Concurrent; using System.Threading.Tasks; class Logger { private readonly ConcurrentBag<string> _logs = new ConcurrentBag<string>(); public void Log(string message) { _logs.Add(message); Console.WriteLine($"Logged: {message}"); } public void DumpLogs() { foreach (var log in _logs) { Console.WriteLine($"Log: {log}"); } } } class Program { static async Task Main() { var logger = new Logger(); var tasks = new Task[3]; tasks[0] = Task.Run(() => logger.Log("Error 1")); tasks[1] = Task.Run(() => logger.Log("Warning 2")); tasks[2] = Task.Run(() => logger.Log("Info 3")); await Task.WhenAll(tasks); logger.DumpLogs(); } }
  • 说明:ConcurrentBag 适合高并发添加场景,日志顺序不重要。

4.5 BlockingCollection:限界任务管道

  • 场景:实现生产者-消费者管道,限制队列大小。
  • 实现:

csharp

using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; class Program { static BlockingCollection<int> buffer = new BlockingCollection<int>(boundedCapacity: 3); static async Task Producer() { for (int i = 1; i <= 5; i++) { buffer.Add(i); // 若缓冲区满,则阻塞 Console.WriteLine($"Produced: {i}"); await Task.Delay(500); } buffer.CompleteAdding(); } static async Task Consumer() { foreach (var item in buffer.GetConsumingEnumerable()) { Console.WriteLine($"Consumed: {item}"); await Task.Delay(1000); } } static async Task Main() { var producer = Task.Run(Producer); var consumer = Task.Run(Consumer); await Task.WhenAll(producer, consumer); } }
  • 说明:BlockingCollection 提供阻塞和限界功能,适合控制资源使用。

5. 并发集合与 Interlocked 的关系

  • 原子操作的使用:ConcurrentQueue 和 ConcurrentStack 内部广泛使用 Interlocked(如 CompareExchange)实现无锁操作。
  • 细粒度锁:ConcurrentDictionary 和 BlockingCollection 可能使用锁,但通过分段锁或信号量优化性能。
  • 性能优化:并发集合封装了 Interlocked 和锁的复杂性,开发者无需直接操作底层原子操作。

6. 注意事项

  • 性能权衡:
    • ConcurrentQueue 和 ConcurrentStack 适合高并发简单操作。
    • ConcurrentDictionary 适合键值对管理,但高并发写入可能因锁竞争降低性能。
    • ConcurrentBag 适合高并发添加,但移除和枚举效率较低。
    • BlockingCollection 适合生产者-消费者场景,但阻塞操作可能影响实时性。
  • 枚举快照:并发集合的枚举(如 foreach)返回快照,可能不反映最新状态。
  • 内存使用:ConcurrentBag 和 BlockingCollection 在高并发场景可能占用较多内存,需监控。
  • 异常处理:并发集合方法(如 TryAdd)返回布尔值,减少异常抛出,需检查返回值。
  • 与 lock 的对比:
    • 并发集合性能通常优于 lock 保护的普通集合。
    • 对于复杂逻辑,lock 或自定义同步可能更灵活。

7. 高级技巧

  • 组合使用:结合多种并发集合实现复杂逻辑。例如,使用 ConcurrentDictionary 存储任务状态,BlockingCollection 实现任务队列。
  • 限界控制:BlockingCollection 的 boundedCapacity 参数可限制内存使用,适合资源受限场景。
  • 异步编程:结合 async/await 和 Task,提高并发集合的响应性。csharp
    async Task ProcessQueueAsync(ConcurrentQueue<int> queue) { while (queue.TryDequeue(out int item)) { await Task.Delay(100); // 模拟异步处理 Console.WriteLine($"Processed: {item}"); } }
  • 分区优化:在极高并发场景下,可为每个线程分配独立的并发集合,最后合并结果,类似 ConcurrentBag 的线程局部存储。

8. 总结C# 的并发集合(ConcurrentDictionary、ConcurrentQueue、ConcurrentStack、ConcurrentBag、BlockingCollection)提供了线程安全的集合操作,内部使用原子操作(如 Interlocked)和细粒度锁优化性能。

它们适用于缓存、任务队列、生产者-消费者模式等场景,简化了并发编程。关键点包括:

  • 选择合适的集合:根据 FIFO、LIFO、无序或阻塞需求选择。
  • 注意性能和内存:高并发场景需测试性能并监控内存。
  • 结合异步编程:利用 async/await 提高响应性。
  • 封装复杂性:并发集合隐藏了底层原子操作和锁的细节,适合大多数场景。

如果您有特定场景(如实现复杂并发数据结构、优化性能或处理特定并发问题),请提供更多细节,我可以进一步提供定制化的代码或深入分析!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 19:03:46

Xiu高级配置技巧:自定义日志、缓存与性能调优

Xiu高级配置技巧&#xff1a;自定义日志、缓存与性能调优 【免费下载链接】xiu A simple,high performance and secure live media server in pure Rust (RTMP[cluster]/RTSP/WebRTC[whip/whep]/HTTP-FLV/HLS).&#x1f980; 项目地址: https://gitcode.com/gh_mirrors/xiu/…

作者头像 李华
网站建设 2026/4/25 18:53:23

智慧建筑物巡检之墙体缺陷监测识别 红外建筑物缺陷检测 建筑缺陷漏水识别 墙体裂缝识别 管道故障检测 深度学习数据集第10432期

建筑热成像计算机视觉数据集说明文档数据集核心信息表项目详情类别数量及中文名称类&#xff08;漏水&#xff09;数据数量300 张&#xff08;热成像图像&#xff09;数据集格式种类YOLO 格式最重要的应用价值支撑建筑领域热成像目标检测模型训练&#xff0c;适用于建筑节能检测…

作者头像 李华
网站建设 2026/4/25 18:53:18

ml-intern预测分析工具:构建未来趋势预测模型

ml-intern预测分析工具&#xff1a;构建未来趋势预测模型 【免费下载链接】ml-intern &#x1f917; ml-intern: an open-source ML engineer that reads papers, trains models, and ships ML models 项目地址: https://gitcode.com/GitHub_Trending/ml/ml-intern ml-i…

作者头像 李华
网站建设 2026/4/25 18:52:39

终极性能优化指南:BAM和CBAM注意力模块的部署与加速技巧

终极性能优化指南&#xff1a;BAM和CBAM注意力模块的部署与加速技巧 【免费下载链接】attention-module Official PyTorch code for "BAM: Bottleneck Attention Module (BMVC2018)" and "CBAM: Convolutional Block Attention Module (ECCV2018)" 项目地…

作者头像 李华