当前位置 博文首页 > 魏小言的博客:Go的并发模型CSP实现

    魏小言的博客:Go的并发模型CSP实现

    作者:[db:作者] 时间:2021-06-24 21:11

    ? ? ? ? 最近抽空研究、整理了一下Golang调度机制,学习了其他大牛的文章。把自己的理解写下来。如有错误,请指正!!!

    ? ? ? ? golang的goroutine机制有点像线程池:
    ? ? ? ? 一、go 内部有三个对象: P对象(processor) 代表上下文(或者可以认为是cpu),M(work thread)代表工作线程,G对象(goroutine).
    ? ? ? ? 二、正常情况下一个cpu对象启一个工作线程对象,线程去检查并执行goroutine对象。碰到goroutine对象阻塞的时候,会启动一个新的工作线程,以充分利用cpu资源。所有有时候线程对象会比处理器对象多很多

    ? ? ? ? 我们用如下图分别表示P、M、G

    ? ? ? ?

    在单核情况下,所有goroutine运行在同一个线程(M0)中,每一个线程维护一个上下文(P),任何时刻,一个上下文中只有一个goroutine,其他goroutine在runqueue中等待。一个goroutine运行完自己的时间片后,让出上下文,自己回到runqueue中(如下图左边所示)。

    当正在运行的G0阻塞的时候(可以需要IO),会再创建一个线程(M1),P转到新的线程中去运行。

    当M0返回时,它会尝试从其他线程中“偷”一个上下文过来,如果没有偷到,会把goroutine放到global runqueue中去,然后把自己放入线程缓存中。上下文会定时检查global runqueue。

    ?

    Go语言是为并发而生的语言,Go语言是为数不多的在语言层面实现并发的语言;也正是Go语言的并发特性,吸引了全球无数的开发者。

    并发(concurrency)和并行(parallellism)

    并发(concurrency):两个或两个以上的任务在一段时间内被执行。我们不必care这些任务在某一个时间点是否是同时执行,可能同时执行,也可能不是,我们只关心在一段时间内,哪怕是很短的时间(一秒或者两秒)是否执行解决了两个或两个以上任务。

    并行(parallellism):两个或两个以上的任务在同一时刻被同时执行。

    并发说的是逻辑上的概念,而并行,强调的是物理运行状态。并发“包含”并行。

    (详情请见:Rob Pike 的PPT)

    Go的CSP并发模型

    Go实现了两种并发形式。第一种是大家普遍认知的:多线程共享内存。其实就是Java或者C++等语言中的多线程开发。另外一种是Go语言特有的,也是Go语言推荐的:CSP(communicating sequential processes)并发模型。

    CSP并发模型是在1970年左右提出的概念,属于比较新的概念,不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存”。

    请记住下面这句话:
    Do not communicate by sharing memory; instead, share memory by communicating.
    “不要以共享内存的方式来通信,相反,要通过通信来共享内存。”

    普通的线程并发模型,就是像Java、C++、或者Python,他们线程间通信都是通过共享内存的方式来进行的。非常典型的方式就是,在访问共享数据(例如数组、Map、或者某个结构体或对象)的时候,通过锁来访问,因此,在很多时候,衍生出一种方便操作的数据结构,叫做“线程安全的数据结构”。例如Java提供的包”java.util.concurrent”中的数据结构。Go中也实现了传统的线程并发模型。

    Go的CSP并发模型,是通过goroutinechannel来实现的。

    • goroutine?是Go语言中并发的执行单位。有点抽象,其实就是和传统概念上的”线程“类似,可以理解为”线程“。
    • channel是Go语言中各个并发结构体(goroutine)之前的通信机制。 通俗的讲,就是各个goroutine之间通信的”管道“,有点类似于Linux中的管道。
    下一篇:没有了