目录
讨论下目前语言的优劣,密集型计算的发展方向,面向并发的内存模型的演进,从几个角度来分析下:
-
CPU
早期语言(C语言),CPU都是以单核的形式顺序执行机器指令。顺序执行意味着在同一时刻只能在一个cpu顺序执行。
单核CPU发展停滞,编程语言逐渐开始朝着多核并行化的方向发展,而Go也是在多核环境下原生支持并发的编程语言典范。 -
内存
常见的并行编程模型有多线程、消息传递等。由于多线程并发模型可以自然对应到多核的处理器,主流的操作系统因此也都提供了系统级的多线程支持,同时从概念上讲多线程似乎也更直观,因此多线程编程模型逐步被吸纳到主流的编程语言特性或语言扩展库中。
每个系统级线程都会有一个固定大小的栈(一般默认可能是2MB),这个栈主要用来保存函数递归调用时的参数和局部变量。固定了栈的大小导致了两个问题:
- 对于很多只需要很小的栈空间的线程是一个巨大的浪费;
- 是对于少数需要巨大栈空间的线程又面临栈溢出的风险
针对这两个问题的解决方案是:要么降低固定的栈大小,提升空间的利用率;要么增大栈的大小以允许更深的函数递归调用,但这两者是无法兼得的
一个Goroutine会以一个很小的栈启动(可能是2KB或4KB),当遇到深度递归导致当前栈空间不足时,Goroutine会根据需要动态地伸缩栈的大小(主流实现中栈的最大值可达到1GB)。因为启动的代价很小,所以我们可以轻易地启动成千上万个Goroutine。
- 调度
线程是系统调度的最小单元,实现抢占式的任务,在共享变量和线程间通信比较复杂。 而协程受程序本身调度,Go语言共享变量的支持很完善,且gorutine间的通信有通道、信号等,消息队列的通信在golang语言中运用非常强大,个人觉得在很多
以往开发习惯上带来便利。