当前位置: 首页 > 科技观察

一篇理解异步和多线程的文章

时间:2023-03-12 02:29:52 科技观察

本文转载自微信公众号《程序新视野》,二师兄丑胖侠作者。转载本文请联系程序新视界公众号。最近在研究SpringBoot中的异步处理,发现了很多异步和多线程相关的知识点。我会先写几篇关于异步和多线程的文章,一起回顾或者学习相关的知识点。开始正文:前言在这篇文章中,我们通过一些通俗易懂的方式来解释异步编程和多线程编程,然后介绍它们之间的区别。什么是异步编程首先来看异步模型。在异步模型中,允许多个事件同时发生(处理)。当程序调用耗时较长的函数(方法)时,不会阻塞程序的执行流程,程序会继续执行。当函数执行完成时,程序可以获得执行完成消息或者可以访问执行结果(如果有返回值或者需要返回值时)。下面举个例子看看同步和异步的区别。例子中,程序通过网络获取两个文件,将两个文件合并:异步和同步上面例子中,异步系统中的解决方案是多开一个线程进行处理。第一个线程拿到第一个文件,第二个线程拿到第二个文件,第二个线程不需要等第一个线程执行完再执行。两个线程都得到相应的结果后,再进行合并结果的操作。我们再看一个场景。单线程方式读取OS(操作系统)中的文件,需要做数学运算。在异步系统中,程序发起读取操作系统中文件的请求。由于读取操作比较耗时,程序会在等待读取文件的同时将控制器交还给CPU进行数学运算。在异步编程中,通常会为耗时函数提供一个函数,函数的参数中包含一个额外的参数用于回调。而这个函数通常被称为回调函数。当耗时函数完成后,通过回调函数返回结果。关于回调函数的知识,请参考文章《两个经典例子让你彻底理解java回调机制》。什么是多线程编程?多线程是指多条指令(线程)并发或并行执行。在单核处理器上,多线程常常给人一种程序并行执行的错觉。实际上,处理器是通过一种调度算法在多个线程之间进行切换和调度的。或者根据外部输入(中断)和线程优先级的组合进行线程切换。在多核处理器上,线程是真正并行运行的。多个处理器同时执行多个线程以实现更高效的处理。一个简单的例子是:打开两个浏览器窗口,同时下载两个文件。每个窗口使用一个新的线程来下载文件,它们之间不需要任何人等待完成,而是并行下载。下图展示了多线程应用程序并发执行的过程:多线程执行异步和多线程的区别通过上面的介绍,我们可以看出多线程就是函数的并发执行。虽然异步编程是关于函数之间的非阻塞执行,但我们可以将异步应用于单线程或多线程。因此,多线程只是异步编程的一种实现。假设您和您的朋友决定一起做午餐。“异步”是你对你的朋友说,“你去商店买意大利面,回来后告诉我,然后我们一起做午饭。你买意大利面,我做番茄酱和饮料。“而“线程”是:“你烧开水,我加热番茄酱。当水沸腾时,告诉我,我把意大利面放进去。当番茄酱热时,你可以加入奶酪。当两者都完成时,你可以坐下来吃晚饭了。”在线程示例中,我们可以看到“When,Do”事件序列,它表示每个人(线程)的一组指令的序列。从上面的例子可以看出,多线程是和具体的executor相关的,而异步是和task相关的。多线程是编程的逻辑层概念。它是在一个进程中并发运行的一段代码,可以实现线程间的切换执行。异步和同步是相对的。异步是相互独立的,在等待事件的同时继续做自己的事情,不需要等到事件完成再工作。多线程是实现异步的一种方式。异步是指调用方法的主线程不需要同步等待另一个线程的完成,这样主线程就可以做其他事情了。所以本质上,异步和多线程并不是等价关系。异步是最终目的,多线程只是实现异步的一种手段。如何选择面对多线程和异步,我们应该如何选择呢?其实通常选择的依据主要是根据性能。那么,在同步/异步和单线程/多线程之间的所有组合中,哪种模型表现更好?总之,对于有大量I/O操作和不同计算的大型应用程序,使用异步多线程是有益的。有利于充分利用计算资源,又能兼顾非阻塞功能。这也是所有操作系统都采用的线程模型。异步操作的编写复杂度高,程序主要采用回调方式进行处理,与正常的思维方式有些不同,调试难度大。使用(滥用)多线程会给系统带来额外的上下文切换负担,线程间共享变量可能会造成死锁。因此,在实现这两种模式时,往往需要处理资源竞争、死锁、共享资源、回调事件等问题。总结在本文中,我们解释了异步编程和多线程编程的定义,然后解释了它们之间的区别。但是,本文中的所有术语和概念与具体的技术实现无关。后面我们会继续讲解异步调用、回调等多线程和异步相关的其他知识点。