私人对于异步与多线程的理解
前言
异步与多线程都是并发问题的一种解决方式,但是异步是程序员层面,线程是操作系统层面的。
其次,异步与线程解决并发问题的实现方式和目的是不同的。下面举一个不太贴切的例子。如果把线程当作一条单行道,那么多线程就是通过扩展多条道路从而实现多车辆(方法、程序)的通行。而异步则是忽略车辆的物理体积,一条路(单线程)可以同时有多辆车通过,不会出现堵车(线程阻塞)情况,谁的速度快谁就跑在前面。
如果是不忽略车辆的物理体积,那么多线程只是解决异步问题的一种手段,但是单线程仍然可以进行异步操作。下面的代码可以更好的理解异步和线程的区别:
例子
我们定义了三个异步任务,在每个异步任务中,我们要求在任务开始执行的时候在控制台打印出线程ID,然后通过延时一秒钟来模拟做点事情,最后,我们依然要求控制台打印出线程ID。
public static async Task FirstAsync()
{
Console.WriteLine("First Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Console.WriteLine("First Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
public static async Task SecondAsync()
{
Console.WriteLine("Second Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Console.WriteLine("Second Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
public static async Task ThirdAsync()
{
Console.WriteLine("Third Async Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(1000);
Console.WriteLine("Third Async Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
现在,我们添加另一个异步方法来执行上面的异步方法
public static async Task ExecuteAsyncFunctions()
{
var firstAsync = FirstAsync();
var secondAsync = SecondAsync();
var thirdAsync = ThirdAsync();
await Task.WhenAll(firstAsync, secondAsync, thirdAsync);
}
最后我们使用main方法来使得整个示例运行:
static async Task Main(string[] args)
{
await ExecuteAsyncFunctions();
}
运行的结果如下:
First Async Method on Thread with Id: 1
Second Async Method on Thread with Id: 1
Third Async Method on Thread with Id: 1
Third Async Method Continuation on Thread with Id: 4
Second Async Method Continuation on Thread with Id: 8
First Async Method Continuation on Thread with Id: 11
我们可以看到刚开始,所有三个异步任务都是在线程ID为1上面运行的,但是经过1秒钟的睡眠,当再次执行异步任务的时候,每个任务又被别的线程执行起来。在这里显示为4,8和11。
为什么会发生这样的事情呢?原因就在于当线程发现关键字await的时候,该线程就会从当前逻辑释放而返回给线程池。一旦睡眠结束,一个新的线程(4,8,11)就重新被分配来执行三个任务。
同样地,我们再看看多线程的代码示例,与上面的例子不同,我们去除了关键字async
public class Multithreading
{
public void FirstMethod()
{
Console.WriteLine("First Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("First Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
public void SecondMethod()
{
Console.WriteLine("Second Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("Second Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
public void ThirdMethod()
{
Console.WriteLine("Third Method on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
Console.WriteLine("Third Method Continuation on Thread with Id: " + Thread.CurrentThread.ManagedThreadId);
}
}
逻辑和之前一样,都是打印线程ID睡眠然后再打印线程ID。同样地,我们创建一个方法,在这个方法里,起三个线程来启动三个任务。最后用main函数运行应用。
public void ExecuteMultithreading()
{
Thread t1 = new Thread(new ThreadStart(FirstMethod));
Thread t2 = new Thread(new ThreadStart(SecondMethod));
Thread t3 = new Thread(new ThreadStart(ThirdMethod));
t1.Start();
t2.Start();
t3.Start();
}
main函数
static async Task Main(string[] args)
{
Multithreading multithreading = new Multithreading();
multithreading.ExecuteMultithreading();
}
运行的结果如下:
First Multithreading Method on Thread with Id: 14
Second Multithreading Method on Thread with Id: 15
Third Multithreading Method on Thread with Id: 16
Second Multithreading Method Continuation on Thread with Id: 15
First Multithreading Method Continuation on Thread with Id: 14
Third Multithreading Method Continuation on Thread with Id: 16
如果我们对比一下异步的例子,就可以得出明显的区别。在多线程的例子里,我们显式地分配了线程,该线程直到做完对应的任务才会结束,即使逻辑当中有一段时间的休眠。
总结
异步编程和多线程编程的区别在于侧重点不同,两者对于提高可用性和性能方面起到了关键性的作用。
参考
https://zhuanlan.zhihu.com/p/570792890
标签:异步,Console,Thread,Method,理解,线程,多线程,Id From: https://www.cnblogs.com/keepingstudying/p/18033142