关于异步与多线程,笔者在刚接触的时候一直存在诸多疑惑,甚至一度以为这俩概念是用来描述同一种技术在不同场景下的应用,进而导致对很多与它们相关的概念都一知半解,代码中的async/await关键词也是莫名其妙地在用。
但是在不断地接触这类概念(因为现在的场景中异步与多线程几乎无处不在)的过程中,还是不断地修正了这种思维。代码写起来也顺手多了。
所以这篇文章也是有感而发,在去年的时间里因为多线程和异步踩了不少雷,希望能够给大家做一点简单的解释和区分把。
TL, DR: 请参照文章最后的例子 :)
多线程是什么多线程 技术有时又称 并行 技术,就是同时做多件事情。这十分好理解,也很直观。
现在的CPU都不止有一个核,每个核都至少具备一个线程,某些CPU具备超线程能力,一个核可以具备多个线程:打开Windows自带的任务管理器,切到性能一栏,选中CPU,线程总数显示在“逻辑处理器”部分。可以看到,笔者这颗 性价比之选 Intel 8700K具备12个线程。
每个线程可以看作是一个流水线,有多个流水线就可以同时运行多段代码,对于某些计算量巨大、同时计算任务又可以拆分的代码,可以将计算任务分配到各个流水线上去,这样就能够更高效地完成指定任务。
总而言之,多线程即 “同时做多件事情”。
下面的代码是一个简单的多线程例子。运行这段代码发现,最后打印的总耗时比每段加起来的耗时要少,这就是并行计算的结果。读者感兴趣可以自行把foreach循环中的有关Task类和lambda函数封包去掉,直接每段运行再进行总耗时求和。
List tasks = new List();Stopwatch sw = Stopwatch.StartNew();foreach (var item in Enumerable.Range(0,3)){ tasks.Add(Task.Run( // lambda函数体 () => { Stopwatch sw = Stopwatch.StartNew(); Thread.Sleep(500); Console.WriteLine($"{sw.ElapsedMilliseconds}ms cost"); } ));}// 等待所有线程退出Task.WaitAll(tasks.ToArray());// 打印计算总耗时Console.WriteLine(string.Format("Total cost: {0}ms", sw.ElapsedMilliseconds)); 异步是什么“异步” 这个概念是对应于 “同步” 概念而言的。“同步”的意思是,所有代码从头至尾按顺序逐条执行,在一行代码执行完之前,不能执行后面的所有代码。下面的例子的中,当Sum()函数被调用的时候,for循环之后的打印 sum 和 Hello World 一定需要等到这个循环结束之后才能被执行。
int Sum(int target){ int sum = 0; for (int ind = 0; ind { for (int ind = 0; ind