线程是执行流的最小单位。线程其实是看不到的,其实也可以,例如 Windows 任务管理器:正在运行 272 个进程,272 个进程运行了 3909 个线程,也就是一个进程可以拥有多个线程。
分时、分片
现在有个怪相,CPU 实在太快了,内存显卡其他硬件资源其实都跟不上 CPU 的速度,于是就产生了分片的概念。从微观角度来讲,以前电脑很多都是单核,一时刻只能执行一个线程,按照这个道理,为什么我们的计算机还可以同时运行许多个应用呢。但从宏观来说是并发的,多个应用同时执行,我们既可以扫雷也可以完蜘蛛纸牌还可以听音乐。这就是分片,分片会产生一个上下文,假设当前执行扫雷线程,下一个时刻执行蜘蛛纸牌线程,CPU 会将扫雷线程上下文保存起来,切换成蜘蛛纸牌线程,这样进行来回调度,从宏观来看是并发的。
这个补充一点额外知识,多 CPU 多核,本身就可以完成多个线程的计算,可以独立工作。4核8线程,核就是物理的核,线程是虚拟的核,每个核可以进行分片做并发的。
我们看下面程序,定义一个普通方法 Sum 做些 CPU 密集型运算,然后在 Main 方法,分别同步与异步,执行 Sum 方法。即同样的任务使用单线程(主线程)运行五次,再使用多线程开启 5 个线程,分别执行。
public static void Sum(int f)
Console.WriteLine($"第{f}次 start:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
decimal s = 0;
for (int i = 0; i < 1000000000; i++)
s = s + i;
Console.WriteLine($"第{f}次 end:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
static void Main(string[] args)
Console.WriteLine($"同步 start:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
for (int i = 0; i < 5; i++)
Sum(i);
Console.WriteLine($"同步 end:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine();
Console.WriteLine($"异步 start:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
for (int i = 0; i < 5; i++)
Action<int> action = Sum;
action.BeginInvoke(i,null,null);
Console.WriteLine($"异步 end:{DateTime.Now.ToLongTimeString()},Thread:{Thread.CurrentThread.ManagedThreadId}");
Console.ReadKey();