go协程
❤ go的协程是一个复杂的模块,它区别于其他语言的线程和进程,独立出一种新的资源管理和调度形式。下面用浅显的话分析一下协程。
1.产生背景
✔在了解go协程之前需要先讲一讲为什么会出现协程。正所谓有需求才会产生解决方案,不然就是空车独行毫无意义。
1.1线程池
对于高并发的业务场景中,我们需要进行线程池的创建,经典线程池包括任务队列,线程池。线程池从任务队列中进行任务调度,获取任务进行处理。线程池会预先创建一定量的线程。这样有助于提高效率。
经典线程池如下所示
1.2线程池瓶颈
在经典线程池中会有一种问题,当线程所执行的任务进行阻塞的系统调用时,此线程会被阻塞,此时工作线程worker就会减少,线程池对于任务队列的消费能力减弱。
当大量线程处于阻塞状态时,任务队列就会产生堆积,cpu的利用率可能会下降。
解决这个问题的方法是增加线程池的最大数量,但是最大数量的增加就意味着线程对cpu的抢占。一定程度上会造成消费能力下降。
这就是问题的产生,于是就产生了go协程来解决这个问题。
2.Goroutine调度器
线程过多,意味着操作系统会不断的进行线程调度,就会跟进程调度一样花费更多的资源。Go中就提供了一种机制,自我进行线程的调用。而进行线程调度的东西就是Goroutine调度器。
Goroutine主要概念如下:
- G(Goroutine): 即Go协程,每个go关键字都会创建一个协程。
- M(Machine): 工作线程,在Go中称为Machine。
- P(Processor): 处理器(Go中定义的一个摡念,不是指CPU),包含运行Go代码的必要资源,也有调度goroutine的能力。
M必须拥有P才可以执行G中的代码,P含有一个包含多个G的队列,P可以调度G交由M执行。其关系如下图所示: