欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C#关于List的线程安全问题

程序员文章站 2022-03-13 21:26:37
...

C# 关于List的线程安全问题

首先,List这个集合类是不安全的。
直接给例子,讲一下吧:

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

namespace vscode_test2
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> mylist = new List<int>();
            var t = Task.Run(()=>{
                Thread.Sleep(2000);
                for(int i=0; i<8000; i++)
                {
                    mylist.Add(3);
                    Thread.Sleep(1);
                }
                System.Console.WriteLine($"task: list size:{mylist.Count}");
            });
            Thread.Sleep(2000);
            for(int i=0; i<5000; i++)
            {
                Thread.Sleep(1);
                mylist.Add(6);
            }
            System.Console.WriteLine($"main: list size:{mylist.Count}");     
            t.Wait();
            Console.Read();
        }
    }
}

/*
main: list size:9753
task: list size:12755
*/

这个例子中,创建了一个类中全局的变量mylist。Task.Run跑了一个额外的线程,它往mylist中插入8000个3, main主线程往mylist中插入5000个6;
然后打印出来列的大小。
由于几乎是同一时刻往mylist中插入数据,因此task后打印信息。
我们查看mylist变量的情况:
C#关于List的线程安全问题
我们可以看到,mylist中的3和6并不是我们想象中的一大片3和一大片6,而是交叉有3和6;并且打印出来的列表大小也并不是想象中的5000,8000或者13000,这就是我们需要特别注意的地方。说明两处for语句,是完全并行执行,互不干扰的。如果你特别强调两处for的插入语句不能被相互打断,那么需要引入"同步"概念,需要lock加锁,或者改用其他线性安全的集合。

相关标签: c# .net core