C# List 並發丟數據問題原因及解決方案

項目中出瞭個 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();
    }

以上就是C# List 並發丟數據問題原因及解決方案的詳細內容,更多關於C# List 並發丟數據的資料請關註WalkonNet其它相關文章!