C# 多线程安全问题
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Task_safe
{
class Program
{
static void Main(string[] args)
{
Task_safe1();
Task_safe2();
Console.ReadKey();
}
public static void Task_safe1()
{
for (int i = 0; i <= 2; i++)
{
Task.Run(() =>
{
Console.WriteLine($"Task_safe1当前i的值为{i}");
});
}
}
public static void Task_safe2()
{
List<int> lt = new List<int>();
for (int i = 0; i <= 10000; i++)
{
Task.Run(() =>
{
lt.Add(i);
});
}
Thread.Sleep(5000);
Console.WriteLine(lt.Count.ToString());
}
}
}
问题1:Task_safe1()中当循环走完0,1,2时Task.Run()实际上还没启动,所以其实Task.Run()真正启动是i已经等于2了,所以打印结果一直为Task_safe1当前i的值为2。
问题2:由于For循环中数据量多,需启动10000线程,这10000个线程有可能其中有几个线程在同一时刻同时执行,因此会出现数据顶掉的情况。所以计数的值会小于10000。
结果:

解决方案
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Task_safe
{
class Program
{
static void Main(string[] args)
{
Task_safe1();
Task_safe2();
Console.ReadKey();
}
public static void Task_safe1()
{
for (int i = 0; i <= 2; i++)
{
int k = i;//添加后就可以
Task.Run(() =>
{
Console.WriteLine($"Task_safe1当前i的值为{k}");
});
}
}
private static readonly object obj = new object();//创建object变量
public static void Task_safe2()
{
List<int> lt = new List<int>();
for (int i = 0; i <10000; i++)
{
Task.Run(() =>
{
lock(obj)//加锁,只有一个线程能进入执行,从而不会出现多个线程同一时间同时进来
{
lt.Add(i);
}
});
}
Thread.Sleep(5000);
Console.WriteLine(lt.Count.ToString());
}
}
}
结果:

浙公网安备 33010602011771号