这篇文章主要介绍“Golang协程池gopool怎么设计与实现”,在日常操作中,相信很多人在Golang协程池gopool怎么设计与实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang协程池gopool怎么设计与实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!Goroutine 是 Golang 提供的一种轻量级线程,我们通常称之为「协程」,相比较线程,创建一个协程的成本是很低的。所以你会经常看到 Golang 开发的应用出现上千个协程并发的场景。Goroutine 的优势:与线程相比,Goroutines 成本很低。它们的堆栈大小只有几 kb,堆栈可以根据应用程序的需要增长和缩小,context switch 也很快,而在线程的情况下,堆栈大小必须指定并固定。Goroutine 被多路复用到更少数量的 OS 线程。一个包含数千个 Goroutine 的程序中可能只有一个线程。如果该线程中的任何 Goroutine 阻塞等待用户输入,则创建另一个 OS 线程并将剩余的 Goroutine 移动到新的 OS 线程。所有这些都由运行时处理,作为开发者无需耗费心力关心,这也使得我们有很干净的 API 来支持并发。Goroutines 使用 channel 进行通信。channel 的设计有效防止了在使用 Goroutine 访问共享内存时发生竞争条件(race conditions) 。channel 可以被认为是 Goroutine 进行通信的管道。在高并发场景下,我们可能会启动大量的协程来处理业务逻辑。协程池是一种利用池化技术,复用对象,减少内存分配的频率以及协程创建开销,从而提高协程执行效率的技术。最近抽空了解了字节官方开源的 gopkg 库提供的 gopool
协程池实现,感觉还是很高质量的,代码也非常简洁清晰,而且 Kitex
底层也在使用 gopool
来管理协程,这里我们梳理一下设计和实现。了解官方 README 就会发现gopool
的用法其实非常简单,将曾经我们经常使用的go func(){...}
替换为gopool.Go(func(){...})
即可。此时 gopool
将会使用默认的配置来管理你启动的协程,你也可以选择针对业务场景配置池子大小,以及扩容上限。old:new:下面我们来看看gopool
是怎样实现协程池管理的。Pool
是一个定义了协程池能力的接口。gopool
提供了这个接口的默认实现(即下面即将介绍的pool
),当我们直接调用 gopool.CtxGo 时依赖的就是这个。这样的设计模式在 Kitex
中也经常出现,所有的依赖均设计为接口,便于随后扩展,底层提供一个默认的实现暴露出去,这样对调用方也很友好。调用 NewPool
获取了以 Pool
的形式返回的 pool
结构体。task
是一个链表结构,可以把它理解为一个待执行的任务,它包含了当前节点需要执行的函数f
, 以及指向下一个task
的指针。综合前一节 pool
的定义,我们可以看到,一个协程池 pool
对应了一组task
。pool
维护了指向链表的头尾的两个指针:taskHead
和 taskTail
,以及链表的长度taskCount
和对应的锁 taskLock
。一个 worker
就是逻辑上的一个执行器,它唯一对应到一个协程池 pool
。当一个worker
被唤起,将会开启一个goroutine
,不断地从 pool
中的 task
链表获取任务并执行。看到这里,其实就能把整个流程串起来了。我们来看看对外的接口 CtxGo(context.Context, f func())
到底做了什么?相信看了代码注释,大家就能理解发生了什么。gopool
会自行维护一个 defaultPool
,这是一个默认的 pool
结构体,在引入包的时候就进行初始化。当我们直接调用 gopool.CtxGo()
时,本质上是调用了 defaultPool
的同名方法defaultPool
的名称为 gopool.DefaultPool
,池子容量一万,扩容下限为 1。当我们调用 CtxGo
时,gopool
就会更新维护的任务链表,并且判断是否需要扩容 worker
:若此时已经有很多 worker
启动(底层一个 worker
对应一个 goroutine
),不需要扩容,就直接返回。若判断需要扩容,就创建一个新的worker
,并调用 worker.run()
方法启动,各个worker
会异步地检查 pool
里面的任务链表是否还有待执行的任务,如果有免费云主机域名就执行。task
是一个待执行的任务节点,同时还包含了指向下一个任务的指针,链表结构;worker
是一个实际执行任务的执行器,它会异步启动一个 goroutine
执行协程池里面未执行的task
;pool
是一个逻辑上的协程池,对应了一个task
链表,同时负责维护task
状态的更新,以及在需要的时候创建新的 worker
。其实到这个地方,gopool
已经是一个代码简洁清晰的协程池库了,但是性能上显然有改进空间,所以gopool
的作者应用了多次 sync.Pool
来池化对象的创建,复用woker和task对象。这里建议大家直接看源码,其实在上面的代码中已经有所涉及。task 池化worker 池化到此,关于“Golang协程池gopool怎么设计与实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注百云主机网站,小编会继续努力为大家带来更多实用的文章!
这篇文章主要讲解了“git怎么还原到某次commit并强制推送远程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“git怎么还原到某次commit并强制推送远程”吧!不可逆提交1.git log查看提交记录2.选…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。