zoukankan      html  css  js  c++  java
  • 异步编程与多线程编程的联系和区别

    参考网址: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有很多相似之处。(详细案例会在后面文章中展示)

  • 相关阅读:
    Jdk 1.6 在线 API 中文版
    数据库的最简单实现
    互联网公司GitHub repo 语言使用情况
    Chrome浏览器查看 iframe信息 OpenFrame
    PostgreSQL 保存json,jsonb类型
    修改PS1变量
    postgres json
    PostgreSQL PL/Python 和 PL/Postgres 函数互相调用
    转:CentOS 6.x 挂载读写NTFS分区(fuse-ntfs-3g)
    CentOS 7 设置静态IP
  • 原文地址:https://www.cnblogs.com/yanan-boke/p/9395638.html
Copyright © 2011-2022 走看看