1 多线程临时变量
2 线程安全和锁lock
3 线程安全策略总结
多线程临时变量
当多线程的循环中使用了循环变量i,就必须使用中间变量临时替代循环变量。
//主线程循环5次,打印i
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"ThreadID:{Thread.CurrentThread.ManagedThreadId.ToString()} 此时i值={i}");
}
//线程池循环5次,打印i
List<Task> taskList = new List<Task>();
for (int i = 0; i < 5; i++)
{
taskList.Add(Task.Run(() =>
{
Console.WriteLine($"taskThreadID:{Thread.CurrentThread.ManagedThreadId.ToString()} 此时i值={i}");
}));
}
Task.WaitAll(taskList.ToArray());
Console.ReadKey();
此时打印:
对比来看,主线程循环变量是0,1,2,3,4。而多线程中的循环变量一直是5,为什么会出现这种情况?
主要原因是:task线程是延迟开启的(延迟时间很少),当开始多线程循环时Console.WriteLine还未执行就已经将5次for循环执行完毕。当打印 i 时候,循环已执行完毕。
因此,需要在线程开启前(且在循环内)用中间变量k去代替循环变量i使用。
//线程池循环5次,打印i
List<Task> taskList = new List<Task>();
for (int i = 0; i < 5; i++)
{
int k = i;
taskList.Add(Task.Run(() =>
{
Console.WriteLine($"taskThreadID:{Thread.CurrentThread.ManagedThreadId.ToString()} 此时i值={k}");
}));
}
Task.WaitAll(taskList.ToArray());
Console.ReadKey();
打印效果: