从‘Hello World’到高并发:用C# Concurrent集合(ConcurrentBag, ConcurrentDictionary)搞定多线程数据共享

从‘Hello World’到高并发:用C# Concurrent集合搞定多线程数据共享

第一次在C#中遇到多线程数据共享问题时,我盯着屏幕上那个诡异的NullReferenceException发了半小时呆——明明单线程测试一切正常,为什么一开多线程就崩溃?这个经历让我意识到,从单线程思维到并发编程的跨越,远不止是Task.Run()那么简单。本文将带你从零构建一个真实的后台任务处理系统,逐步揭示传统集合在多线程环境中的陷阱,以及如何用System.Collections.Concurrent命名空间下的神器(特别是ConcurrentBagConcurrentDictionary)优雅解决这些问题。

1. 为什么我们需要线程安全集合?

假设你正在开发一个电商促销系统,需要实时统计来自全国各地的秒杀请求。单线程版本简单直接:

var requestCounts = new Dictionary<string, int>();
void ProcessRequest(string region) 
{
    if (!requestCounts.ContainsKey(region))
        requestCounts[region] = 0;
    requestCounts[region]++;
}

这段代码在单线程环境下完美运行,但当我们尝试用并行处理提升性能时:

Parallel.For(0, 1000, _ => ProcessRequest("华东"));
Console.WriteLine(requestCounts["华东"]);  // 输出可能小于1000!

三个致命问题会突然出现

  1. 丢失更新:多个线程同时执行requestCounts[region]++时,增量操作可能被覆盖
  2. 键值竞争ContainsKey检查和后续赋值不是原子操作
  3. 状态损坏:内部数据结构可能因并发修改而崩溃

传统解决方案是使用lock

private static readonly object _lock = new object();
void ProcessRequestSafe(string region)
{
    lock (_lock) {
        if (!requestCounts.ContainsKey(region))
            requestCounts[re
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值