Kotlin 协程实践之进程、线程、协程

用户头像
陈吉米
关注
发布于: 2020 年 05 月 18 日
Kotlin协程实践之进程、线程、协程

本文自Roman Elizarov在KotlinConf 2018关于Kotlin协程演讲和笔者构建网络爬虫服务实践过程中的一些总结而来。



由于篇幅和精力限制,打算分多篇文章逐步写作完成,敬请期待!



知其然才能知其所以然,为了能用好协程,我们不得不先从一些理论开始!

进程、线程、协程

为了了解为什么要提出协程这一概念,让我们先来回顾一下历史。



进程

进程是操作系统里面的概念。操作系统最大的需求是要“同时”运行多个任务(程序),于是用进程来封装和抽象这个需求。程序运行在进程中,进程中的程序会感觉到一个假象,自己独立占用了CPU资源,感觉自己一直被执行。



当然这只是个假象,操作系统通过如抢占式分片时间来进行调度。这种抽象的好处在于操作系统负责了这个复杂性,而程序只负责自己的逻辑代码即可。如果让每个程序来考虑如何分时使用CPU,那么对于程序员来说,是个灾难吧。



线程



进程是一个重型资源,包括独立的内存空间、文件句柄、状态等等等等,这里我们不需要详细描述。做个想象实验,在一个操作系统上创建100进程,在一个JVM中创建100线程,哪个更快?



线程也是一种抽象,暂且我们认为是程序级别的抽象。随着一个进程(程序)中,逻辑越来越复杂,需要“同时”存在多个相互独立的逻辑,比如一个负责UI事件、一个负责绘画、一个负责数据库查询计算等。



和进程一样,从程序员的角度看这个问题,此时需要线程这个抽象概念来解决问题,不然程序会很复杂。为什么不创建多个进程呢?前面我们说过进程是重资产,太昂贵。线程比进程更为轻量,因为线程们共享同一个进程的内存空间等资源。甚至操作系统都可以感知不到线程概念存在。同样由操作系统和程序来共同欺骗线程,让线程感觉自己独立占用了CPU来执行自己的指令。



不去考虑用户态线程还是核心态线程的实现方式,Java提供了一个统一Thread的抽象。其他语言的Runtime也会类似提供支持。仅仅只有Thread还不够编写完美的程序,因为线程共享内存空间,不得不额外提供Lock、信号量等工具,让线程们可以相互配合来完成工作。



协程



协程并不是一个新的概念,不过对于Java程序员而言是比较陌生。



有了进程、线程这个两个抽象后,程序员们过着幸福无比的生活,写出了很多复杂强大的软件。但是随着高并发、高负载、C10K问题越来越困扰程序员们。



一个核心的原因在于Block(阻塞)。



比如线程中的代码,执行一个IO请求,此时线程被Block,也就是IO请求没有返回之前,线程不能做其他任何事情了。



那么Block会引起什么问题?比如你系统中有10工作线程,假设每个线程处理一个用户请求花费1秒钟,这一秒钟包括了IO等待的990毫秒,10毫秒是CPU计算时间。那么请问在这个一秒钟内,如果来了第11个用户请求怎么办?答案自然是排队等待了。也就是说这个系统1秒内最多处理10个请求。当然你也可以创建更多工作线程来提高吞度量。虽然线程是轻量资源,但是是相对进程而言,实际上你在一个JVM里面去创建10000个线程试试,可能直接崩溃。



因为CPU很快,IO却很慢,一个是火箭速度、一个是蚂蚁在爬行。线程这个抽象的问题在于,在系统执行IO时,线程傻傻等待,浪费大把美好时光,从而造成系统吞吐量过低。



所以程序员们需要一个新的抽象来解决这个问题,“不要阻塞”。



为了让线程在遇到IO阻塞时,能不闲着,去做其他事情。此刻就需要把程序逻辑封装在一个叫协程的抽象里面。



如果程序逻辑被装在协程里面,那么上面的例子中,只需要一个线程,系统吞度量就可以提升到100/s.



所以协程的存在是为了避免线程被Block卡住。



小结

本篇简单介绍了站在程序员角度,进程、线程、协程三个抽象概念如何帮助他们完成编程任务,以及三个抽象的优缺点。



下一篇: Kotlin 协程实践(2)之 异步和Callback地狱



发布于: 2020 年 05 月 18 日 阅读数: 1150
用户头像

陈吉米

关注

奥卡姆剃刀道理很简单,实践起来很难 2017.11.30 加入

jimichan@gmail.com https://github.com/mayabot

评论 (3 条评论)

发布
用户头像
感谢分享,博客推荐到InfoQ首页了。
2020 年 05 月 18 日 10:09
回复
谢谢,一定高质量完成这个系列!
2020 年 05 月 18 日 11:43
回复
期待,我们随时关注,有问题也可以找我们编辑沟通。
2020 年 05 月 18 日 13:30
回复
没有更多了
Kotlin协程实践之进程、线程、协程