百科问答小站 logo
百科问答小站 font logo



Golang 的 goroutine 是如何实现的? 第1页

  

user avatar   yi-wang-43 网友的相关建议: 
      

更新说明:这个答案是在golang1.8的时候搬运的,现在随着时间的推移,请大家多多关注golang本身的进化,这个答案或许还有效,但是没有与时俱进的更新,多多包涵。

The Go scheduler 纯翻译如下:

Go runtime的调度器:
在了解Go的运行时的scheduler之前,需要先了解为什么需要它,因为我们可能会想,OS内核不是已经有一个线程scheduler了嘛?
熟悉POSIX API的人都知道,POSIX的方案在很大程度上是对Unix process进场模型的一个逻辑描述和扩展,两者有很多相似的地方。 Thread有自己的信号掩码,CPU affinity等。但是很多特征对于Go程序来说都是累赘。 尤其是context上下文切换的耗时。另一个原因是Go的垃圾回收需要所有的goroutine停止,使得内存在一个一致的状态。垃圾回收的时间点是不确定的,如果依靠OS自身的scheduler来调度,那么会有大量的线程需要停止工作。

单独的开发一个GO得调度器,可以是其知道在什么时候内存状态是一致的,也就是说,当开始垃圾回收时,运行时只需要为当时正在CPU核上运行的那个线程等待即可,而不是等待所有的线程。

用户空间线程和内核空间线程之间的映射关系有:N:1,1:1和M:N
N:1是说,多个(N)用户线程始终在一个内核线程上跑,context上下文切换确实很快,但是无法真正的利用多核。
1:1是说,一个用户线程就只在一个内核线程上跑,这时可以利用多核,但是上下文switch很慢。
M:N是说, 多个goroutine在多个内核线程上跑,这个看似可以集齐上面两者的优势,但是无疑增加了调度的难度。


Go的调度器内部有三个重要的结构:M,P,S
M:代表真正的内核OS线程,和POSIX里的thread差不多,真正干活的人
G:代表一个goroutine,它有自己的栈,instruction pointer和其他信息(正在等待的channel等等),用于调度。
P:代表调度的上下文,可以把它看做一个局部的调度器,使go代码在一个线程上跑,它是实现从N:1到N:M映射的关键。


图中看,有2个物理线程M,每一个M都拥有一个context(P),每一个也都有一个正在运行的goroutine。
P的数量可以通过GOMAXPROCS()来设置,它其实也就代表了真正的并发度,即有多少个goroutine可以同时运行。
图中灰色的那些goroutine并没有运行,而是出于ready的就绪态,正在等待被调度。P维护着这个队列(称之为runqueue),
Go语言里,启动一个goroutine很容易:go function 就行,所以每有一个go语句被执行,runqueue队列就在其末尾加入一个
goroutine,在下一个调度点,就从runqueue中取出(如何决定取哪个goroutine?)一个goroutine执行。

为何要维护多个上下文P?因为当一个OS线程被阻塞时,P可以转而投奔另一个OS线程!
图中看到,当一个OS线程M0陷入阻塞时,P转而在OS线程M1上运行。调度器保证有足够的线程来运行所以的context P。


图中的M1可能是被创建,或者从线程缓存中取出。

当MO返回时,它必须尝试取得一个context P来运行goroutine,一般情况下,它会从其他的OS线程那里steal偷一个context过来,
如果没有偷到的话,它就把goroutine放在一个global runqueue里,然后自己就去睡大觉了(放入线程缓存里)。Contexts们也会周期性的检查global runqueue,否则global runqueue上的goroutine永远无法执行。


另一种情况是P所分配的任务G很快就执行完了(分配不均),这就导致了一个上下文P闲着没事儿干而系统却任然忙碌。但是如果global runqueue没有任务G了,那么P就不得不从其他的上下文P那里拿一些G来执行。一般来说,如果上下文P从其他的上下文P那里要偷一个任务的话,一般就‘偷’run queue的一半,这就确保了每个OS线程都能充分的使用。


user avatar   teng-xun-ji-zhu-gong-cheng 网友的相关建议: 
      

克劳备忘录也好,凯南电报也好,有两大共同点。首先,都是以现实主义的眼光去分析双方的关系。然后,给出的建议都是阳谋,并不是什么不可告人的阴谋,执行起来需要的不是鸡鸣狗盗的小聪明,而是惊人的意志力。

而美国现在战略界现实主义被边缘化,我推测,布热津斯基,基辛格那帮人应该写过不少。不过没所谓,美国能执行大战略的时代过去了。现在这一代精英上半年能管下半年就已经很了不起了。一个需要两代人以上持之以恒去完成的大战略,搞出来他们也执行不了。

冷战时期,从杜鲁门艾森豪威尔到肯尼迪尼克松,最后到李根老布什,个人性格和政治偏好差距不要太大,但是都忠实地完成了他们历史任务,沿着围堵政策做下去。这种战略定力和延续性,世间少见。在中国领导集团上能看见一些相似的东西,但是我们离得距离太近,反而看不清。但在美国精英层身上完全看不到这一点。

个人愚见。


user avatar   he-hong-zhou-62 网友的相关建议: 
      

说实话,在这个问题下,台湾人的看法无足轻重。

这么说也没有什么不公平,因为台湾人的无足轻重不是我们造成的。

台湾问题原本只是内战遗留问题,但随着蒋氏政权终结,美日经过多年渗透已经逐渐掌控了台湾的政局。任何一个谋求台湾大位的候选人几乎都必须以各种方式获得美国支持,这已经是公开并且形成惯例的。美日早年支持的各种社会团体,掌握了大量政治资源,甚至是资金。

那些所谓的本土派,也只是相对原果党遗老而言。这些本土派本身除了提出台独,根本也没有什么提升台湾本土利益的政治主张,否则莱猪这个事就完全无法解释。

所以,台湾实际上正在趋向1984年前后的香港的形势。就是真正的话事人走到前台,是统是独都决定不了的人,说什么没人在意。

1984年香港人参与中英谈判,英国人不可能允许。1985年之后英国人在香港推行有一定实质性的代议制,到90年代初,英国想让港英政府的人参与,邓小平也不允许呀

所以,应对啥?

我们该想的是,我们登岛解放台湾之后,怎么安慰那些一时还不接受现状的人。我教你一个:小ww别难过,再过50年就好了!




  

相关话题

  应该如何理解 Erlang 的「任其崩溃」思想? 
  为什么C语言整型常量十进制形式的类型与八进制、十六进制的不一样? 
  什么才算是真正的编程能力? 
  C「带坏了」多少程序语言的设计? 
  C 语言是否需要改进,甚至重新设计一门语言取代 C 语言? 
  C 语言这些宏定义前面的 __extension__ 是什么意思? 
  十大编程语言都有哪些?哪种比较好? 
  有哪些c++的书推荐? 
  为什么没有新的支持底层达到类似C++这种程度,而易用性达到C#的语言出现? 
  不同编程语言的程序员之间有鄙视链么? 

前一个讨论
如何看待肃宁枪击案牺牲政委妻子跳楼身亡?
下一个讨论
RoboMaster是一个什么样的机器人比赛?





© 2024-06-18 - tinynew.org. All Rights Reserved.
© 2024-06-18 - tinynew.org. 保留所有权利