Go 线程的3种实现模型

代码领航说
• 阅读 1866

go语言的并发模型

     无论语言层面的哪种并发模型,到了操作系统层面一定是以线程的形态存在的,操作系统根据资源访问权限的不同,体系架构可以分为用户空间(不可以直接调用系统资源,必须通过系统调用,函数库,shell脚本等调用内核空间的资源)和内核空间(主要访问CPU资源,内存资源,io等硬件资源,为上一层的应用程序提供基础资源)。
    我们现在计算机语言比如Java,Go里面的线程指的都是用户空间里的线程,和操作系统内核空间的线程是不同的,Go语言的并发模型底层是由操作系统提供的线程库来支撑的,所以下面就先从线程模型说起。

线程模型

    线程可以看做进程中的控制流,一个进程至少包含一个线程,因为在进程执行的时候,至少会有一个控制流持续执行。
    所以一个进程的第一个线程会随着一个进程的启动而创建,这个线程经常被叫做主线程。一个进程中可以包含多个线程,这些线程是被已经存在的线程创建出来的。另一方面,线程不可以独立于进程存在,线程的生命周期不可逾越进程的生命周期。
    拥有更多个线程的进程就可以并发的执行多个任务,并且就算某一个任务被阻塞,其他任务也可以正常运行,这样就可以大大改善程序的响应时间和吞吐量。
    线程的实现模型主要有3个,用户级线程模型,内核级线程模型,两级线程模型。他们之间最大的差异就在于线程和内核调度实体(kernel schedule entity KSE)之间的对应关系上。

内核级线程模型

    也叫一对一模型,用户线程和内核线程是一对一的映射关系,如果有一个线程阻塞不会影响其他线程,目前很多线程库(比如Linux, Java, Cpp)都是对操作系统的线程进行一层封装,之后创建出来的线程可以和不同的静态线程互相关联。由于这样的调度动作都是由操作系统完成,所以实现特别简单,直接借助操作系统提供的线程操作能力即可,并且可以在多和操作系统上实现真正的并行,但是这样线程的创建、销毁、多个上下文之间的切换都是由操作系统层面亲自处理,所以消耗的性能代价很大。

用户级线程模型

    也叫做多对一模型,将多个用户级线程映射到一个内核级线程上,这样线程的创建、销毁、多个上下文之间的切换操作都由用户自己实现的线程库负责,对操作系统的内核来说是透明的,一个进程中所有创建出来的线程都和同一个内核级线程动态关联,目前有很多语言实现的协程都是用的这个方法。优点是,相比于内核级线程模型,可以做的很轻量级,极大减少对系统资源的消耗。缺点是,如果在某个用户线程中调用阻塞式系统调用,比如read去读系统IO,这样,一旦内核线程被阻塞线程调度出CPU,所有其他线程都会变成阻塞状态导致整个进程被挂起。(所以,这些语言的协程库往往会采用将阻塞式操作重新封装成非阻塞形式,在之前要阻塞的点上主动让出自己,并且通过某种方式主动唤醒其他线程在当前的内核线程上执行),本质上只利用了一个处理器,不适用于多核处理器,知识解决了并发问题,没有解决并行的问题。

两级线程模型

    也叫做混合线程模型或者多对多线程模型,用户线程和内核线程是多对多的,一个进程中创建了多个KSE,线程可以和不同的内核线程进行动态关联,当某一个线程被调度处CPU的时候同组的其他线程可以和其他的内核线程建立连接,这种动态关联机制 较为复杂,Go的并发就是使用这种方式,为了实现这种模型,Go自己实现了一个运行时调度器(Goroutine Processor Machine 简称GPM)来负责goroutine和内核线程进行动态关联。这样的好处是,可以让大部分线程的上下文切换都发生在用户线程内,多个线程模型又可以充分利用处理器的资源。

参考资源:bilibili

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Linux 多线程编程
1.Linux“线程”进程与线程之间是有区别的,不过Linux内核只提供了轻量进程的支持,未实现线程模型。Linux是一种“多进程单线程”的操作系统。Linux本身只有进程的概念,而其所谓的“线程”本质上在内核里仍然是进程。大家知道,进程是资源分配的单位,同一进程中的多个线程共享该进程的资源(如作为共享内存的全局变量)。Linux
Wesley13 Wesley13
3年前
Java8内存模型
<divclass"htmledit\_views"<h1<aname"t0"</a一、JVM内存模型</h1<p</p<p<spanstyle"fontfamily:'宋体';"内存空间</span(RuntimeDataArea)中可以按照是否线程共享分为两块,线程共享的是方法区(MethodArea)和堆
Stella981 Stella981
3年前
Eclipse插件开发_学习_00_资源帖
一、官方资料 1.eclipseapi(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fhelp.eclipse.org%2Fmars%2Findex.jsp%3Ftopic%3D%252Forg.eclipse.platform.doc.isv%252Fguide%2
Stella981 Stella981
3年前
Linux 多线程
I.同步机制线程间的同步机制主要包括三个:互斥锁:以排他的方式,防止共享资源被并发访问;互斥锁为二元变量,状态为0开锁、1上锁;开锁必须由上锁的线程执行,不受其它线程干扰.条件变量:
Wesley13 Wesley13
3年前
Java 中传统多线程
@TOCJava中传统多线程线程初识线程的概念当代操作系统中,可以独立并发执行的基本单元轻量:占用系统资源极少独立:操作系统可以独立调度和分派的基本单元共享:共享进程中的资源实现线程继承Thread类,重写run方法实现Runnable接口,实现run方法pack
Wesley13 Wesley13
3年前
Java线程安全总结
浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(