有电脑网站怎样建手机,正规网络游戏平台,免费软件制作网站模板,衡水建网站Go并发基础
并行#xff1a;程序在任意时刻内都是同时运行的 并发#xff1a;程序在单位时间内都是同时运行的 扇入#xff1a;多条通道聚合到一条通道中#xff08;select聚合#xff0c;加密解密服务#xff09; 扇出#xff1a;一条通道发散到多条通道中#x…Go并发基础
并行程序在任意时刻内都是同时运行的 并发程序在单位时间内都是同时运行的 扇入多条通道聚合到一条通道中select聚合加密解密服务 扇出一条通道发散到多条通道中goroutine实现并发Web服务器并发处理用户请求
在java/c中我们要实现并发编程的时候我们通常需要自己维护一个线程池并且需要自己去包装一个又一个的任务同时需要自己去调度线程执行任务并维护上下文切换。
Go语言中的goroutine就是这样一种机制goroutine的概念类似于线程但 goroutine是由Go的运行时runtime调度和管理的。Go程序会智能地将 goroutine 中的任务合理地分配给每个CPU。Go语言之所以被称为现代化的编程语言就是因为它在语言层面已经内置了调度和上下文切换的机制。
1goroutine可以在用户空间调度避免内核态和用户态的切换。
2goroutine是语言原生支持的屏蔽了大部分复杂底层实现。
3goroutine更小的栈空间允许用户创建更多的实例。
Go语言并行调度原理
GPM是Go语言运行时runtime层面实现是go语言自己实现的一套调度系统。区别于操作系统调度OS线程。 G就是goroutine它不是一个运行实体而是用于存放并发执行的代码入口地址上下文运行环境关联的P和M运行栈等元信息。为了减少对象的分配和回收G对象可以被复用执行完的goroutine可以重新初始化。 PProcessor管理着一组goroutine队列P是存储当前goroutine运行的上下文环境函数指针堆栈地址及地址边界的一个数据结构而非控制实体P会对自己管理的goroutine队列做一些调度比如把占用CPU时间较长的goroutine暂停、运行后续的goroutine等等当自己的队列消费完了就去全局队列里取如果全局队列里也消费完了会去其他P的队列里抢任务。 Mmachine是Go运行时runtime对操作系统内核线程的虚拟是操作系统层面调度和运行的实体。 M与内核线程一般是一一映射的关系 一个groutine最终是要放到M上执行的M仅负责执行资源来自于P和GP与M一般也是一一对应的。他们关系是 P管理着一组G挂载在M上运行。当一个G长久阻塞在一个M上时runtime会新建一个M绑定相应的P阻塞G所在的P会把其他的G 挂载在新建的M上。当旧的G阻塞完成或者认为其已经死掉时 回收旧的M。 M拥有自己的栈g0但只有当拿到P才可以执行M会在堆栈g0上恢复G的上下文完成后切换到G的栈开始执行
Go启动初始化过程
分配和检查栈空间。初始化参数和环境变量。当前运行线程标记为m0即程序主线程。调用运行时初始化函数runtime.schedinit 进行初始化。(内存空间分配GC生成空闲P列表)在m0上调度第一个G这个G负责运行runtime.main函数。runtime.main会拉起运行时的监控线程(对应一个M专门监控、控制程序的内存和调度信息)然后调用main包的init()初始化函数最后执行main函数。
总结
一个操作系统线程对应用户态多个goroutine。go程序可以同时使用多个操作系统线程。goroutine和OS线程是多对多的关系即m:n。
命令作用runtime.GOMAXPROCS(x)x0时为查询可以并发执行的goroutine数目 x0时为设置GOMAXPROCS值runtime.Goexit结束当前goroutine运行(会调用其defer但是不会产生panic)runtime.Gosched放弃当前调度执行的机会将当前goroutine放到Processor的队尾runtime.NumGoroutine返回当前程序的goroutine个数
Go语言为什么并行更快
Go语言相比起其他语言的优势在于OS线程是由OS内核来调度的goroutine则是由Go运行时runtime自己的调度器调度的这个调度器使用一个称为m:n调度的技术复用/调度m个goroutine到n个OS线程。 goroutine的调度是在用户态下完成的 不涉及内核态与用户态之间的频繁切换包括内存的分配与释放都是在用户态维护着一块大的内存池 不直接调用系统的malloc函数除非内存池需要改变成本比调度OS线程低很多。 另一方面充分利用了多核的硬件资源近似的把若干goroutine均分在物理线程上 再加上本身goroutine的超轻量以上种种保证了go调度方面的性能。