参考网址:https://blog.csdn.net/qq_27825451/article/details/78853119

  

1、异步编程与多线程的区别

共同点:异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性

不同点:

        (1)线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

                 多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线              程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现

      (2)异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完                全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序              主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。

        这里有一个疑问。异步操作没有创建新的线程,我们一定会想,比如有一个文件操作,大量数据从硬盘上读取,若使用单线程的同步操作自然要等待会很长时间,但是若使用异步操作的话,我们让数据读取异步进行,二线程在数据读取期间去干其他的事情,我们会想,这怎么行呢,异步没有创建其他的线程,一个线程去干其他的事情去了,那数据的读取异步执行是去由谁完成的呢?实际上,本质是这样的。

        熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

       即CPU在数据的长时间读取过程中 ,只需要做两件事,第一发布指令,开始数据交换;第二,交换结束,得到指令,CPU再进行后续操作。而中间读取数据漫长的等待过程,CPU本身就不需要参与,顺序执行就是我不参与但是我要干等着,效率低下;异步执行就是,我不需要参与那我就去干其他事情去了,你做完了再通知我就可以了(回调)。

       但是你想一下,如果有一些异步操作必须要CPU的参与才能完成呢,即我开始的那个线程是走不开的,这该怎么办呢,在.NET中,有线程池去完成,线程池会高效率的开启一个新的线程去完成异步操作,在python中这是系统自己去安排的,无需人工干预,这就比自己创建很多的线程更加高效。

总结:

       (1)“多线程”,第一、最大的问题在于线程本身的调度和运行需要很多时间,因此不建议自己创建太大量的线程;第二、共享资源的调度比较难,涉及到死锁,上锁等相关的概念。

       (2)“异步” ,异步最大的问题在于“回调”,这增加了软件设计上的难度。

在实际设计时,我们可以将两者结合起来:

       (1)当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。异步特别适用于大多数IO密集型的应用程序。
       (2)而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处 理大量的并发操作时就不合适了。

2、在多线程编程和异步编程上的进步(以.NET和python语言为例进行说明)

       多线程最大的问题在于“线程的调度”,而在.NET中引入了线程池的概念,避免人为创建多余线程,让系统进行分配;而Python语言中的多线程编程效率一直饱受诟病,因此python很少使用多线程,一般使用“协程”,后面会讲到。

      异步最大的问题在于“回调”,.NET随着版本的升级,从多任务编程,到后面使用await-async关键字的提升,让人更加方便,不用注意到复杂的回调问题,用同步的思维方式进行异步编程。python从3.4版本开始也开始使用协程和时间循环机制,从yield和yield from 语句中受到启发,解决了“回调问题”,而在python3.5版本中,也是使用了await-async关键字,进一步简化了编程。在这一方面,python和.NET有很多相似之处。(详细案例会在后面文章中展示)