C# List 并发丢数据问题原因及解决方案

作者:丹枫无迹 时间:2023-06-18 17:53:54 

项目中出了个 BUG,就在我眼皮子底下,很明显的一个 BUG,愣是看了两天才看出来。

我有多个任务并发,任务执行完成后都有一个返回结果,我用一个 List 将结果收集起来,等所有任务完成后,发送出去。结果一直 丢数据。

我反复检查逻辑都没有问题,最后恍然 List 是非线程安全的。

大家都知道 List 是非线程安全的,但是如果仅有 Add 操作呢?估计有些人就会认为没问题。

下面的代码,期望输出的结果是 1000,然而,注释掉 lock 后,结果就不一样了。


class Program
{
static List<Person> persons;

static void Main(string[] args)
{
 persons = new List<Person>();

object sync = new object();

Parallel.For(0, 1000, (i) =>
 {
  Person person = new Person
  {
   ID = i,
   Name = "name" + i
  };
  lock (sync)
   persons.Add(person);
 });

Console.WriteLine(persons.Count);
 Console.ReadLine();
}

class Person
{
 public int ID { get; set; }
 public string Name { get; set; }
}
}

利用安全集合ConcurrentBag取代list

测试程序


using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyConcurrent
{
 class Program
 {
   /// <summary>
   /// ConcurrentBag并发安全集合
   /// </summary>
   public static void ConcurrentBagWithPallel()
   {
     ConcurrentBag<int> list = new ConcurrentBag<int>();
     Parallel.For(0, 10000, item =>
     {
       list.Add(item);
     });
     Console.WriteLine("ConcurrentBag's count is {0}", list.Count());
     int n = 0;
     foreach (int i in list)
     {
       if (n > 10)
         break;
       n++;
       Console.WriteLine("Item[{0}] = {1}", n, i);
     }
     Console.WriteLine("ConcurrentBag's max item is {0}", list.Max());
   }

/// <summary>
   /// 函数入口
   /// </summary>
   /// <param name="args"></param>
   static void Main(string[] args)
   {
     Console.WriteLine("ConcurrentBagWithPallel is runing" );
     ConcurrentBagWithPallel();

Console.Read();
   }

来源:https://www.cnblogs.com/gl1573/p/14392108.html

标签:c#,list,并发
0
投稿

猜你喜欢

  • c#基于opencv,开发摄像头播放程序

    2023-06-20 11:54:29
  • VS2019 找不到资产文件 “xxxx\\obj\\project.assets.json”运行NuGet包还原以生成此文件(解决方案)

    2021-08-25 10:41:05
  • SpringCloud实现Eureka服务注册与发现

    2021-08-16 04:00:44
  • 你知道jdk竟有4个random吗

    2022-06-14 23:37:08
  • WinForm开发中屏蔽WebBrowser脚本错误提示的方法

    2021-06-23 08:49:40
  • java编程实现优先队列的二叉堆代码分享

    2022-11-13 15:32:13
  • Maven Repository仓库的具体使用

    2021-11-04 21:33:34
  • 详解怎么用Java的super关键字

    2021-10-06 08:11:14
  • 使用jpa之动态插入与修改(重写save)

    2021-07-04 21:02:26
  • 让Java后台MySQL数据库能够支持emoji表情的方法

    2022-12-30 04:24:45
  • C# 8.0可空引用类型的使用注意记录

    2022-10-03 23:29:40
  • C#使用Twain协议实现扫描仪连续扫描功能

    2023-02-15 18:14:38
  • java设计模式之外观模式学习笔记

    2022-07-02 18:48:06
  • SpringBoot生产环境和测试环境配置分离的教程详解

    2022-04-03 22:09:47
  • Kotlin Lambda表达式实践使用介绍

    2023-08-16 06:11:14
  • C#简单了解接口(Interface)使用方法

    2022-01-30 18:33:57
  • 递归出现栈溢出stackoverflow的问题及解决

    2023-01-29 16:36:10
  • Android串口通信之串口读写实例

    2023-11-04 00:11:03
  • 基于ArrayList源码解析(基于JDK1.8)

    2021-10-07 18:34:25
  • 详解c# 深克隆与浅克隆

    2023-09-06 18:00:07
  • asp之家 软件编程 m.aspxhome.com