首页 > 其他 > 详细

golang学习笔记 ---面向并发的内存模型

时间:2018-12-10 21:30:19      阅读:154      评论:0      收藏:0      [点我收藏+]

Go语言是
基于消息并发模型的集大成者,它将基于CSP模型的并发编程内置到了语言中,通
过一个go关键字就可以轻易地启动一个Goroutine,与Erlang不同的是Go语言的
Goroutine之间是共享内存的。

Goroutine和系统线程

Goroutine是Go语言特有的并发体,是一种轻量级的线程,由go关键字启动。在真
实的Go语言的实现中,goroutine和系统线程也不是等价的。尽管两者的区别实际
上只是一个量的区别,但正是这个量变引发了Go语言并发编程质的飞跃。

 

系统线程

每个系统级线程都会有一个固定大小的栈(一般默认可能是2MB),这个栈
主要用来保存函数递归调用时参数和局部变量。

固定了栈的大小导致了两个问题:
一是对于很多只需要很小的栈空间的线程来说是一个巨大的浪费,二是对于少数需
要巨大栈空间的线程来说又面临栈溢出的风险。针对这两个问题的解决方案是:要
么降低固定的栈大小,提升空间的利用率;要么增大栈的大小以允许更深的函数递
归调用,但这两者是没法同时兼得的。

Goroutine

相反,一个Goroutine会以一个很小的栈启动

(可能是2KB或4KB),当遇到深度递归导致当前栈空间不足时,Goroutine会根据
需要动态地伸缩栈的大小(主流实现中栈的最大值可达到1GB)。

因为启动的代价
很小,所以我们可以轻易地启动成千上万个Goroutine。

Go的运行时还包含了其自己的调度器,这个调度器使用了一些技术手段,可以在n
个操作系统线程上多工调度m个Goroutine。Go调度器的工作和内核的调度是相似
的,但是这个调度器只关注单独的Go程序中的Goroutine。Goroutine采用的是半抢
占式的协作调度,只有在当前Goroutine发生阻塞时才会导致调度;同时发生在用户
态,调度器会根据具体函数只保存必要的寄存器,切换的代价要比系统线程低得
多。运行时有一个 runtime.GOMAXPROCS 变量,用于控制当前运行正常非阻塞
Goroutine的系统线程数目。

在Go语言中启动一个Goroutine不仅和调用函数一样简单,而且Goroutine之间调度
代价也很低,这些因素极大地促进了并发编程的流行和发展。

golang学习笔记 ---面向并发的内存模型

原文:https://www.cnblogs.com/saryli/p/10099124.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!