从冯·诺依曼发明世界上第一台机计算机后,很长一段时间内,计算机都没有操作系统。人们只能在计算机上运行单个程序,那时候使用计算机正常的流程为,输入运行指令、执行运行指令、得到运算结果。因为计算机只能按照步骤顺序执行,所以输入运行指令和执行运行指令不能并发的执行。导致输入运行指令浪费了宝贵的计算机资源。
一、进程
为了解决资源分配问题,提高计算机的利用率,聪慧的人儿研究出了操作系统,程序在各自的进程中独立运行,由操作系统来平衡协调资源。进程是操作系统资源分配的基本单位,每一个进程都有独立的代码和数据空间,程序之间的切换会有较大的开销。
二、线程
在进程之后,为了进一步平衡资源的调度,减少进程切换的资源的巨大开销,大佬们又引入了线程,线程可以理解为“轻量级的进程”,它是处理器任务调度和执行的基本单位,在同一个进程内,线程之间共享内存地址空间,可以实现访问相同的变量,共同使用同一个堆。所以从进程间数据共享到线程间数据共享,提高了宝贵计算机资源的利用率。并且因为线程是轻量级的进程,所以线程创建、销毁比进程快。但凡事有利必有弊,线程间的数据共享带来的问题是,如果没有一个明确的同步管理数据共享,线程之间数据会互相篡改影响,达不到程序运行的期望。这就是并发编程要解决的一个很重要的问题。
三、协程
说完线程,来谈谈协程吧,协程可以理解为线程的线程。线程虽然提升了资源的利用率,但是也存在线程资源有限,而且大多数线程资源处于阻塞的状态,线程之间的开销虽然对比进程少了不少,但是上下文切换的切换开销也不小的问题。协程的出现在一定程度上解决了一些问题。协程的核心在于调度那块由他来负责解决,遇到阻塞操作,立刻放弃掉,并且记录当前栈上的数据,阻塞完后立刻再找一个线程恢复栈并把阻塞的结果放到这个线程上去跑,等达到一定条件后,再恢复原来的栈信息继续执行。协程在Java原生库上不支持的,要引入三方的库才支持。Kotlin和Go语言是原生支持协程的。