博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Goroutine与线程的区别
阅读量:6477 次
发布时间:2019-06-23

本文共 1658 字,大约阅读时间需要 5 分钟。

文章引用自gopl的9.8章节

动态栈

每一个OS线程都有一个固定大小的内存块(一般会是8MB)来做栈,这个栈会用来存储当前正在被调用或挂起(指在调用其他函数时)的函数的内部变量。这个固定大小的栈同时很大又很小。因为2MB的栈对于一个小小的gorourine来说是很大的内存浪费,比如对于我们用到的,一个只是用来WaitGroup之后关闭channel的goroutine来说。而对于go程序来说,同时创建成百上千个goroutine是非常普遍的,如果每一个goroutine都需要这么大的栈的话,那这么多的goroutine就不太可能了。

相反,一个goroutine会以一个很小的栈开始其生命周期,一般只需要2kb。一个goroutine的栈,和操作系统线程一样,会保存其活跃或挂起的函数调用的本地变量,但是和OS线程不太一样的是一个goroutine的栈大小并不是固定的,栈的大小会根据需要动态地伸缩。而goroutine的栈的最大值有1GB,比传统的固定大小的线程栈要大得多,尽管一般情况下,大多goroutine都不需要这么大的栈。

调度

OS线程会被操作系统内核调度。每几毫秒,一个硬件计时器会中断处理器,这会调用一个叫作scheduler的内核函数。这个函数会挂起当前执行的线程,并将它的寄存器中的内容保存到内存中,检查线程列表并决定下一次哪个线程可以被运行,并从内存中恢复该线程的寄存器信息,然后恢复执行该线程的现场并开始执行线程。因为操作系统线程是被内核所调度,所以从一个线程向另一个线程“移动”需要完整的上下文切换,也就是说,保存一个用户线程的状态到内存,恢复另一个线程的状态到寄存器,然后更新调度器的数据结构。这几步操作很慢,因为其局限性很差,需要几次内存访问,并且会增加运行的CPU周期。

Go在运行时包含了其自己的调度器,这个调度器使用了一些技术手段,比如m:n调度(m:goroutine数,n:系统线程数),因为其会在n个操作系统线程上调度m个goroutine。Go调度器的工作和内核的调度是相似的,但是这个调度器只关注Go程序中的goroutine。和操作系统的线程调度不同的是,Go调度器并不是用一个硬件计时器而是被Go语言本身进行调度的。例如当一个goroutine调用了time.Sleep或者被channel调用或者mutex操作阻塞时,调度器会使其进入休眠并开始执行另一个goroutine直到时机成熟再去唤醒第一个goroutine。因为这种调度方式不需要进入内核的上下文,所以重新调用一个goroutine比调用一个线程代价要低得多。

GOMAXPROCS

Go的调度器使用一个叫做GOMAXPROCS的变量来决定会有多少个操作系统的线程同时执行Go的代码。其默认值是运行机器上的CPU核心数,所以在一个8核心的机器上时,调度器一次会在8个OS线程上去调度Go代码。(GOMAXPROCS是前面说的m:n调度中的n)。在休眠中的或者在通信中被阻塞的goroutine是不需要一个对应的线程来做调度的。在I/O中或系统调用中或调用非Go语言函数时,是需要一个对应的操作系统线程的,但是GOMAXPROCS并不需要将这几种情况计数在内。简而言之,GOMAXPROCS不计算阻塞线程数。

Goroutine没有ID号

在大多数支持多线程的操作系统和程序语言中,当前的线程都有一个独特的身份(ID),并且这个身份信息可以以一个普通值的形式被很容易的获取到,典型的可以是一个integer或者指针值。这种情况下我们做一个抽象化的thread local storage(线程本地存储,多线程编程中不希望其他线程访问的内容)就很容易,只需要以线程的ID作为key的一个map就可以解决问题,每个线程以其ID就能获取到值,且和其他线程互不冲突。

goroutine没有可以被程序员获取到的身份(ID)的概念。这一点设计上故意为之,防止thread local storage被滥用。

转载地址:http://ktqko.baihongyu.com/

你可能感兴趣的文章
[转载]ASP.NET MVC3 及其学习资源
查看>>
JavaScript 中对变量和函数声明的“提前”
查看>>
非阻塞算法-栈
查看>>
java 打开记事本
查看>>
狗 日 的 360
查看>>
Policy in Reinforcement Learning
查看>>
.net 通过NPOI或MyXls把DataTable导出到Excel
查看>>
GBK编码和UTF-8编码互转的大坑
查看>>
SQL Server Profiler(一)
查看>>
利用@media screen实现网页布局的自适应
查看>>
ajax取json数据——简单的
查看>>
css一像素问题
查看>>
使用Eclipse进行远程调试【转】
查看>>
【POJ】2418 Hardwood Species
查看>>
powerDesigner16.5 -导入数据库表结构
查看>>
css3动画:执行前不显示,执行后显示
查看>>
passport.js学习笔记
查看>>
PHP - 用户异常断开连接,脚本强制继续执行,异常退出回调
查看>>
常见端口 HTTP代码
查看>>
理解Mysql的单索引和复合索引
查看>>