Parallel線程安全問題

廢話很少說,上代碼:編程

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ParallelTest
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Product> products = new List<Product>();
             Parallel.For(0, 1000000, (i) =>
            {
                Product product = new Product();
                product.Name = "name" + i;
                product.Category = "Category" + i;
                product.SellPrice = i;
                products.Add(product);
            });
            
            Console.WriteLine(products.Count);
            Console.ReadLine();
        }
    }

    class Product
    {
        public string Name { get; set; }

        public string Category { get; set; }

        public int SellPrice { get; set; }
    }
}

猜一下,運行結果是多少,是999999?抱歉不是的,結果!= 999999。數組

運行結果

Net 4.0引入了System.Threading.Tasks,簡化了咱們進行異步編程的方式,而不用直接與線程和線程池打交道,但這也引入了線程安全問題。安全

System.Threading.Tasks中的類型被稱爲任務並行庫(TPL)。TPL使用CLR線程池(說明使用TPL建立的線程都是後臺線程)自動將應用程序的工做動態分配到可用的CPU中。多線程

其中Parallel是指數據並行,其提供的Parallel.For()或Parallel.ForEach()方法,能夠以並行方式對數組或集合中的數據進行迭代。異步

那之因此出現這個結果,很顯然了,是多線程操做集合致使的線程安全問題。異步編程

總之,多線程操做集合時必定要注意線程安全的問題,無論是經過Thread、ThreadPool、Task、Parallel仍是PLINQ。spa

解決方案很簡單:線程

  1. 加鎖
  2. 使用並行集合(System.Collections.ConCurrent)

對於這個問題,我知道其存在潛在的線程安全問題,可是不肯定其致使的結果如何?當我截圖處處詢問無果時,纔想到本身動手寫demo去驗證問題。這也是我寫這篇文章的初衷:提醒本身,遇到問題,不要憑空猜想,要有動手驗證的決心。code

相關文章
相關標籤/搜索