go协程的概念

进程和线程和协程:

  • 进程是程序在操作系统中的一次执行过程,每个进程中至少包含一个线程(主线程)。
  • 线程是CPU调度的基本单位,一个线程上可以跑多个协程(协程是轻量级的线程)。
  • goroutine就是由官方实现的"线程池"。一个协程对应一个函数,每个go关键字都会创建一个协程。也可以创建多个goroutine执行相同的函数。

并发和并行

  • 并发:多线程程序在单核cpu上运行。
  • 并行:多线程程序在多核cpu上运行。

高并发是指系统能够同时处理很多请求。 

go协程高并发的原因:

  • OS线程(操作系统线程)一般有固定为2MB的栈内存,而一个协程的栈在开始时只有2KB左右的栈,会按需增大和缩小。
  • 由于实现机制而大幅减少创建和销毁的开销。

goroutine主要概念如下:

  • G(Goroutine): 即Go协程,除了存放本goroutine信息外还有与所在P的绑定等信息。
  • M(Machine):工作线程,在Go中称为Machine。是对操作系统内核线程的虚拟,M与内核线程一般是一一映射的关系, 一个协程最终是要放到M上执行的;
  • P(Processor): 处理器(是Go中定义的一个摡念,不是指CPU),包含运行Go代码的必要资源,管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界)。

P的个数在程序启动时决定,可以使用runtime.GOMAXPROCS()设置P的个数(最大256),默认为CPU处理器个数。

P会对自己管理的goroutine队列做一些调度(比如把占用CPU时间较长的goroutine暂停、运行后续的goroutine)当自己的队列消费完了就去全局队列里取,如果全局队列里也消费完了会去其他P的队列里抢任务。

M必须拥有P才可以执行G中的代码,所以同时运行的M个数(线程数)一般等于CPU处理器个数,以达到尽可能地使用CPU而又不产生过多的线程切换开销。

理论上当某个Goroutine进入系统调用时,会有一个新的M被启用或创建,继续占满CPU。但由于Go调度器检测到M被阻塞是有一定延迟的,即旧的M被阻塞和新的M得到运行之间是有一定间隔的。

所以在并发量大的时候可以把P设大一点,但不要太多,切换太频繁的话得不偿失。

单从线程调度讲,Go语言的优势在于OS线程是由OS内核来调度的,goroutine则是由Go运行时自己的调度器调度的。这个调度器使用一个称为m:n调度的技术(调度m个goroutine到n个OS线程)。 其一大特点是goroutine的调度是在用户态下完成的, 不涉及内核态与用户态之间的频繁切换,包括内存的分配与释放,都是在用户态维护着一块大的内存池, 不直接调用系统的malloc函数(除非内存池需要改变),成本比调度OS线程低很多。

另一方面充分利用了多核的硬件资源,近似的把若干goroutine均分在物理线程上, 再加上本身goroutine的超轻量,以上种种保证了go调度方面的性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值