37.知乎回答

有了线程,为什么还要有协程?

在计算机科学的历史上协程这个概念的出现要早于线程,如果你去看《计算机程序设计艺术》这本书,Knuth老爷子这里专门提到协程,实际上你该问既然有了协程为什么还要有线程?

说实话这两个没有任何本质的区别,说到底线程也好协程也把无非就是执行流的暂停与恢复,从现代操作系统的角度来看协程实现在用户态,线程实现在内核态。

为什么线程这么流行呢?因为线程这个概念把执行流管理的复杂度“封装”在了操作系统中,对程序员可不见,使用起来更加方便,但协程就不一样了,不是随随便便哪个程序员能在用户态搞定执行流管理的,这个相对复杂,现代编程语言近近几年开始支持协程,否则你需要自己造轮子,这导致其很难用,难用的东西从来都流行不起来,想一想为什么iPhone要用图形界面而不是给你一个命令行界面 呢?

为什么编程更关注内存而很少关注CPU?

我来告诉你答案吧,真相只有一个,之所以你很少关心CPU是因为:

编译器和操作系统替你关心了。

如果你的工作是编写编译器或者操作系统那么不关心CPU是寸步难行的,编写编译器不理解CPU怎么生成机器指令?不理解CPU怎么优化机器指令?编写操作系统不理解CPU怎么实现操作系统的初始化任务?怎么才能实现线程切换?

要知道整个计算机系统是有层次的,最下层是硬件,然后是操作系统,接着是编译器,然后是各种语言,最后才是基于语言的各种应用程序。

从这个角度看,之所以你觉得不需要关心CPU是因为你的工作层次在最表层,在这这里当然是不需要要关心CPU的,也没办法关心。

但内存就不一样了,不管你在哪个层次工作,程序总是要操作数据的吧,数据总是要放在内存吧,数据的使用方式决定了需要栈和堆这两种区域,程序员必须决定数据放在哪里,这个工作没人能够替代。

而对于抽象层次更高的语言,堆栈都省了。

因此当你总在应用层工作就会觉需要关心内存而不需要关心CPU。

为什么会出现复杂指令集的CPU?就拿intel举例吧,为什么英特尔采用的是x86 而不是risc阵营的指令集呢?

问题1:为什么会出现复杂指令集? 1970s年代,这一时期编译器还非常菜,不像现在这么智能,没多少人信得过编译器,大部分程序还是用汇编语言纯手工编写,因此大家普遍认为指令集应该更加丰富一些、指令本身功能更强大一些,程序员常用的操作最好都有对应的特定指令,毕竟大家都在直接用汇编语言来写程序,如果指令集很少或者指令本身功能单一,那么程序员用汇编指令写起程序会会非常繁琐,很不方便,如果你在这个时期用汇编写程序你也会这样想。

在这一时期,计算机的内存只有几KB大小,可谓寸土寸金,这么小的内存要想装入更多的程序就必须仔细的设计机器指令以节省程序占据的空间,这就要求:a),一条机器指令尽可能完成更多的任务;b) 机器指令长度不固定,也就是变长机器指令,简单的指令占据更少的空间;c),机器指令高度编码(encoded),提高代码密度,节省空间。

这是基于这样的现状使得复杂指令集的出现成为必然。

问题2:为什么英特尔采用的是x86而不是risc阵营的指令集呢? 很简单,因为英特尔生产x86处理器时,risc阵营还不存在。