Go线程模型

介绍

先介绍一下常见的三种线程模型,然后再介绍Go中独特的线程模型

三种线程模型

线程的并发执行是由操作系统来调度的,然而操作系统一般在内核提供对线程的支持,我们在编程的过程中创建的线程是用户线程,用户线程与内核线程有什么关系呢?下面要讲解的三种线程模型是根据用户线程和内核线程关系的不用而区分的

一对一模型

这种线程模型是用户线程与内核线程是一一对应的,当前进程对应的主线程就是用户线程,也就是对应一个内核线程,如下图所示:


一对一模型.png

这种线程模型的优点在于在多处理器上,多个线程可以真正地实现并行,而不是只有并发。并且当一个线程由于执行系统调用等原因被阻塞的时候,其他的线程不受影响。
缺点在于一般操作系统会限制内核线程的个数,所以用户线程的个数也会受到限制。另外由于用户线程与系统线程一一对应的关系,当用户线程执行系统调用的时候,需要从用户态执行的程序切换到内核态,等执行完系统调用后,又会从内核态切换回用户态,而这个切换的代价是非常大的。

多对一模型

多对一模型是指多个用户线程对应一个内核线程,同一时刻同一个内核线程只能对应一个用户线程。这时候对应同一个内核线程的多个用户线程的上下文切换是在用户态进行的,不由操作系统调用的。其模型图如下:


多对一模型

这种模型的好处在于上下文切换是在用户态进行的,所以切换的速度很快,开销很小。可创建的用户线程也可以很多,只受内存的大小限制。这种模型由于是多个用户线程对应一个内核线程,当该内核线程对应的一个用户线程被阻塞挂起的时候,该内核线程的其他用户线程也不能运行了。另外这种模型并不能很好地利用多核CPU进行并行运行。

多对多模型

多对多模型结合上述两种模型的特点,让大量的用户线程对应少数几个内核线程,其模型图如下:


多对多模型

这时候每个内核线程对应多个用户线程,每个用户线程可以对应多个内核线程。当一个用户线程阻塞后,其对应的内核线程会被阻塞,但是被阻塞的内核线程的其他用户线程可以切换到其他内核线程上继续运行,所以多对多模型是可以充分利用多核CPU提升运行效率的。多对多模型对用户线程的个数没有限制,理论上只要内存足够就可以。

Go线程模型

Go线程模型属于多对多线程模型,其模型图如下:


Go线程模型

Go语言中使用go语句创建的goroutine可以认为是轻量级的用户线程(协程也是轻量级的用户线程),go线程模型包含三个概念:内核线程(M),goroutine(G),逻辑处理器(P),在Go中每个逻辑处理器(P)会绑定到某一个内核线程(M)上,每个逻辑处理器(P)内有一个本地队列,用来存放goroutine。在上面介绍的多对多线程模型中是操作系统调度线程在物理CPU上运行,在Go中则是Go在运行时调度goroutine在逻辑处器(P)上运行的。
在Go中存在两极调度,一级是操作系统的调度,该调度系统调度逻辑处理器占用CPU时间片运行的,还有一级是Go的运行时的调度系统,该调度系统调度某个goroutine在逻辑处理器(P)上运行。
使用Go语句创建一个goroutine后,创建的goroutine会被放入Go运行时调度器的全局队列中,然后Go运行时调度器会把全局队列中的goroutine分配给不同的逻辑处理器(P),分配的goroutine会被放到逻辑处理器(P)的本地队列中,当本地队列中里的goroutine就绪并且待分配后,就会被分配到逻辑处理器(P)上运行。如上图goroutine1当前正在占用逻辑处理器1在运行。
这里需要注意的是,为了避免某些goroutine出现饥饿现象,被分配到某一个逻辑处理器(P)上的多个goroutine是分时在该逻辑处理器(P)上运行的,而不是独占逻辑处理器(P)运行到结束。比如某个goroutine从开始运行到结束运行需要5分钟,那么当前逻辑处理器(P)下的另外其他goroutine并不是顺序执行的,而是交叉并发执行的。
goroutine内部实现与在多个操作系统线程之间复用的协程(coroutines)一样,如果有一个goroutine阻塞操作系统线程,则该操作系统线程对应的逻辑处理器(P)中其他的goroutine将迁移到其他操作系统线程中,以便它们可以继续运行,如下图所示:


切换逻辑处理器

如上图左图,假设goroutine1在执行某些系统调用的时候,则goroutine1会导致内核线程1阻塞,这时候Go运行时调度器会把goroutine1所在的逻辑处理器1迁移到其他的内核线程上,这时候逻辑处理1上的goroutine2和goroutine3就不会受goroutine1的影响了。等goroutine1的系统调用执行完后,goroutine1又会被Go运行时调度系统重新放入到逻辑处理器1的本地队列。
默认情况下,Go是给每个可用的物理处理器都分配一个逻辑处理器(P),如果需要修改逻辑处理器(P)的个数可以通过函数runtime.GOMAXPROCS函数。

goroutine(G)的数量也是可以创建很多个,理论只要内存够大,可以无限制创建。

总结

正是由于这样的线程模型才让Go中每台机器可以创建成千上万的goroutine。我们也需要特别了解其中的PMG模型。


2021.9.30 16:29 深圳

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容