异步并发程序的技术选择

异步,是相对于同步(顺序)而言的。并发,是相对于单一而言的。

异步执行,而不是同步阻塞。比如程序需要去读写文件,然后再执行一个不相关的任务。我们可以改造这个程序,把读写文件的操作变成异步的,不等它执行,就去执行下一个不相关的任务。再在程序结束前等待异步读写文件的步骤完成。这种方法,能缩短这个程序的响应时间。这种改造,适合响应实时性要求高的程序。值得注意的是,这种方法并不意味着并发多任务。如果异步执行的是IO,通常意味着异步IO库的支持;如果异步执行的是其他的本地耗时代码,则通常意味着使用使用一个线程池,此时就属于并发执行了。

操作系统创建进程、线程,都是相对耗时的操作。因此,现代语言大部分都提供了线程池,复用这些内核对象。这是进行并发程序设计时需要注意的。

程序并发执行时,如果访问共享的资源,则需要保证合理的访问顺序,从而获得预期的执行结果。锁定、互斥,是常用的控制方法。

并发执行的程序步骤,我们时常会遇到任务之间存在依赖的情况。任务之间的等待管理也是程序设计中常遇到的问题。早期经常使用 callback。近来来经常使用 Future Promise 来将互相依赖的并行任务串起来。而 await async语法糖则使得我们可以像编写串行程序一样来写并行程序,而且依赖(等待)管理的粒度更细。不过,await async这种“像串行”的代码风格也是有一定争议的。把两种本质不同的代码写得看上去很像,在可读性、可理解性上,有时会造成困难。因此,在运用于生产代码之中时,应该以一致可理解为主要原则,选用合适的风格和技术,而不是总使用最新的。这些机制,在C++, Java, JavaScript, Python, Golang等中都有提供。

在此基础之上,我们经历了多核多进程、分布式多机器、多容器等方法,来利用多台设备协作,提高程序的处理能力和性能。

而合理优化的算法、自身开销小的编程语言,对于提高程序基本组成模块的性能,有更决定性的影响。比如Python语言,在处理大规模的数据计算时相当慢,numpy等数字处理库通过C/C++语言扩展,提供了很多性能优化。通过对程序算法的优化,能减少对设备的要求,这对于大规模使用设备的服务商内部而言,能节省很多运营开支。

而对于服务商的客户们而言,服务商则尽量提供方便的基础设施,从而使得客户可以专注于业务软件开发。如果客户的软件需要使用大量的计算资源,那么理解服务商的资源提供方式,从而在所用的软件开发语言上进行一定的优化,也可以减少开支,但这也意味着服务商销售收入的减少。