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变量的情况:
我们可以看到,mylist中的3和6并不是我们想象中的一大片3和一大片6,而是交叉有3和6;并且打印出来的列表大小也并不是想象中的5000,8000或者13000,这就是我们需要特别注意的地方。说明两处for语句,是完全并行执行,互不干扰的。如果你特别强调两处for的插入语句不能被相互打断,那么需要引入"同步"概念,需要lock加锁,或者改用其他线性安全的集合。