sync.Pool代码阅读

最近阅读了一下pool.go的代码,相应的查了一些网上的资料。

sync.Pool在标准库中实现的目的是封装重用的数据结构和功能。实际生产环境中,大量应用中需要用到缓存,也导致会有多种pool实现出来,golang遵循软件工程的理念,直接搞到标准库中,这样大家也不用挖空心思压榨cpu了。

这里有个几个注意点

  • 就是chan也有缓存的作用,chan天然线程安全,不过我们需要的pool是put(x)和get()这种,chan是需要写入和读取的,写入和读取都会收到并发限制。
  • 当然用户也可以自己实现pool,实现方法五花八门,可以使用sync.Mutex或者sync.RWMutex都可以,当然用户需要关心goroutine在使用pool时的并发性能是否已经是极限,然后需要做大量的调试,最后能搞出一个相对稳定的版本。

在说明sync.Pool的设计方式之前,需要对P这个概念做一些说明。可以参考 :

如果想要了解sync.Pool就需要对P这个东西有一定程度的认知,P是goroutine的调度器,内核中执行goroutine真正工作的是thread,为了增加并发度,golang利用P作为调度器,可以在单内核上模拟多goroutine并发的感觉,同时也会在空闲时从其他忙碌的cpu上偷goroutine执行,这样能让cpu更就均衡的执行。

sync.Pool的实现方式:

  • 为每个P分配一个poolLocal,用于缓存数据,分摊存储压力。内部有privateshared两种缓存,private类似cpu寄存器,快速但是存储空间小;shared类似内存,没有边界限制,允许goroutine并发访问(用Mutex管理)。
  • Pool维护指针local指向poolLocal列表,主要是在初始化和销毁对象时使用。

poolLocal两级缓存都miss时,会从其他P偷取shared并返回这个shared中的数据。这样和groupcache很像,是不是仅可能防止缓存被穿透,会收到业务大量的Put请求增加cpu负载。

sync.Pool代码阅读
Share this