goroutine和线程区别

从调度上看,goroutine的调度开销远远小于线程调度开销。程序员

OS的线程由OS内核调度,每隔几毫秒,一个硬件时钟中断发到CPU,CPU调用一个调度器内核函数。这个函数暂停当前正在运行的线程,把他的寄存器信息保存到内存中,查看线程列表并决定接下来运行哪个线程,再从内存中恢复线程的注册表信息,最后继续执行选中的线程。这种线程切换须要一个完整的上下文切换:即保存一个线程的状态到内存,再恢复另一个线程的状态,最后更新调度器的数据结构。某种意义上,这种操做仍是很慢的。编程

Go运行的时候包涵一个本身的调度器,这个调度器使用一个称为一个M:N调度技术,m个goroutine到n个os线程(能够用GOMAXPROCS来控制n的数量),Go的调度器不是由硬件时钟来按期触发的,而是由特定的go语言结构来触发的,他不须要切换到内核语境,因此调度一个goroutine比调度一个线程的成本低不少。数据结构

 

从栈空间上,goroutine的栈空间更加动态灵活。多线程

每一个OS的线程都有一个固定大小的栈内存,一般是2MB,栈内存用于保存在其余函数调用期间哪些正在执行或者临时暂停的函数的局部变量。这个固定的栈大小,若是对于goroutine来讲,多是一种巨大的浪费。做为对比goroutine在生命周期开始只有一个很小的栈,典型状况是2KB, 在go程序中,一次建立十万左右的goroutine也不罕见(2KB*100,000=200MB)。并且goroutine的栈不是固定大小,它能够按需增大和缩小,最大限制能够到1GB。编程语言

 

goroutine没有一个特定的标识。函数

在大部分支持多线程的操做系统和编程语言中,线程有一个独特的标识,一般是一个整数或者指针,这个特性可让咱们构建一个线程的局部存储,本质是一个全局的map,以线程的标识做为键,这样每一个线程能够独立使用这个map存储和获取值,不受其余线程干扰。操作系统

goroutine中没有可供程序员访问的标识,缘由是一种纯函数的理念,不但愿滥用线程局部存储致使一个不健康的超距做用,即函数的行为不只取决于它的参数,还取决于运行它的线程标识。线程

 

reference: 《Go程序设计语言》设计

相关文章
相关标签/搜索