ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Go语言实现轻量级线程池

2022-03-21 18:03:37  阅读:249  来源: 互联网

标签:workerpool 创建 Goroutine worker 线程 轻量级 Go pool


相对于操作系统线程,Goroutine 的开销十分小,一个 Goroutine 的起始栈大小为 2KB,而且创建、切换与销毁的代价很低,可以创建成千上万甚至更多 Goroutine。所以和其他语言不同的是,Go 应用通常可以为每个新建立的连接创建一个对应的新 Goroutine,甚至是为每个传入的请求生成一个 Goroutine 去处理。

Goroutine 的开销虽然“廉价”,但也不是免费的

一旦规模化后,这种非零成本也会成为瓶颈。以一个 Goroutine 分配 2KB 执行栈为例,100w Goroutine 就是 2GB 的内存消耗。

其次,Goroutine 从Go 1.4 版本开始采用了连续栈的方案,也就是每个 Goroutine 的执行栈都是一块连续内存,如果空间不足,运行时会分配一个更大的连续内存空间作为这个 Goroutine 的执行栈,将原栈内容拷贝到新分配的空间中来。连续栈的原理决定了,一旦 Goroutine 的执行栈发生了 grow,那么即便这个 Goroutine 不再需要那么大的栈空间,这个 Goroutine 的栈空间也不会被 Shrink(收缩)了,这些空间可能会处于长时间闲置的状态,直到 Goroutine 退出。

另外,随着 Goroutine 数量的增加,Go 运行时进行 Goroutine 调度的处理器消耗,也会随之增加,成为阻碍 Go 应用性能提升的重要因素。

Goroutine 池是一种常见的解决方案。这个方案的核心思想是对 Goroutine 的重用,也就是把 M 个计算任务调度到 N 个 Goroutine 上,而不是为每个计算任务分配一个独享的 Goroutine,从而提高计算资源的利用率。

workerpool 的实现原理

workerpool 有很多种实现方式,这里为了更好地演示 Go 并发模型的应用模式,以及并发原语间的协作,这里采用完全基于 channel+select 的实现方案,不使用其他数据结构,也不使用 sync 包提供的各种同步结构,比如 Mutex、RWMutex,以及 Cond 等。

workerpool 的实现主要分为三个部分:

  • pool 的创建与销毁;

  • pool 中 worker(Goroutine)的管理;

  • task 的提交与调度。

capacity 是 pool 的一个属性,代表整个 pool 中 worker 的最大容量。使用一个带缓冲的 channel:active,作为 worker 的“计数器”

源代码

workerpool 文件对外主要提供三个 API:

  • workerpool.New:用于创建一个 pool 类型实例,并将 pool 池的 worker 管理机制运行起来;
  • workerpool.Free:用于销毁一个 pool 池,停掉所有 pool 池中的 worker;
  • Pool.Schedule:这是 Pool 类型的一个导出方法,workerpool 包的用户通过该方法向 pool 池提交待执行的任务(Task)。

标签:workerpool,创建,Goroutine,worker,线程,轻量级,Go,pool
来源: https://www.cnblogs.com/ltaodream/p/16035787.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有