go的并发编程goroutine

    xiaoxiao2021-03-25  225

    首先搞清楚几个概念

    线程实现模型主要有三种:

    KSE是内核调度实体,又称内核级线程,就是可以被内核调度器调度的对象

    用户级线程模型:此模型下的线程由用户级别的线程库管理,线程库在进程的用户空间中。包含多个用户级线程的进程

              只与一个KSE对应,又被称为M:1线程模型

              优点:线程切换不需要让CPU从用户态切换到内核态

              缺点:多线程不能被真正的并发执行

    内核级线程模型:此模型下的线程是由内核负责管理的,进程中的每一个线程都与一个KSE对应(确定关联),又被称            为1:1线程模型

               优点:即使一个线程受到阻塞线程,其他线程也不会受到影响

               缺点:内核线程管理成本高很多,线程切换需要进行用户太-内核态-用户态转变

    两级线程模型:(同时包含内核级和用户级线程管理)一个进程可以与多个KES相连,又称为M:N线程模型,与内核级线程           模型类似,但不相同的是进程中的用户级线程与KSE并不一一对应,在go语言中不受内核管理的独立控           制流(两级线程模型的中的用户级线程管理)就叫Goroutine

    协程:又称为轻量级线程。携程的特点是单线程的。协程不是函数调用。最大的优势就是协程极高的执行效率。因为

    子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数

    量越多,协程的性能优势就越明显。第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同

    时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

    再来看Goroutine,Goroutine采用两级线程模型。

    go语言主要实现模型

    M:代表一个内核级线程

    P:代表一个M所需的上下文

    G:就是我们所写的go一段并发代码

    P中包含一个可与运行G队列

    G需要一个M+P才可以执行

    M数量一般与P(GOMAXPROCS)的数量大致一样,当M运行的G系统调用(例如io操作)时,这个M会与它所关联的P分开,从而多出一个空闲P,如果P队列中拥有未运行的G,体统会找一个空闲M或新建一个M来执行G

    M代表一个内核级线程,本质是一个用户级线程,与一个内核调度实体相关联,由内核控制单线程M的并发

    M为单线程协程实现,用户级调度控制我们Go的并发代码

    从总体上说,内核始终相连M(除特殊情况),在M内实现协程,即由我们决定什么时候调度G去执行,而由内核决定什么时候去调度M(分配CPU)

    最终实现在一个程序(进程)中,一个并发代码G可以被关联到多个内核调度实体,既利用了多核,又利用了协程减少了线程切换的代价

              

    转载请注明原文地址: https://ju.6miu.com/read-495.html

    最新回复(0)