golang sync.Pool的用法及实现

1.基本概念

正如sycn.Pool的名字所示,这是go中实现的一个对象池,为什么要有这个池呢?首先go是自带垃圾回收机制(也就是通常所说的gc)。gc会带来运行时的开销,对于高频的内存申请与释放,如果将不用的对象存放在一个池子中,用的时候从池子中取出一个对象,用完了再还回去,这样就能减轻gc的压力。

对于池这个概念,之前可能听说过连接池。能否用sync.Pool实现一个连接池呢?答案是不能的。因为对于sync.Pool而言,我们无法保证每次放回去再取出来的对象是与之前一致的,对象的内存存在着呗销毁的可能。因此,这个sync.Pool的存在仅仅是为了减缓gc的压力而生的。

2.特点

  • sync.Pool是一个存储临时对象的对象池
  • 任何存储在sync.Pool中的变量随时都有可能被销毁,并且销毁的同时没有任何通知
  • pool中的对象数量是不可控的
  • 当pool中只有一个对象时,这块内存有可能被回收
  • sync.Pool是协程安全的

3.基本用法

import (
    "fmt"
    "sync"
)

func main() {
    p := &sync.Pool{
        New: func() interface{} {
            return "test"
        },
    }

    s := p.Get().(string)
    fmt.Println(s)
    p.Put(s)
}

定义sync.Pool的时候只需要设置一个New成员,它是一个函数,类型为func() interface{},当池子中没有空闲的对象时就会调用New函数生成一个。由于pool中对象的数量不可控,因此并没有传递任何与对象数量有关的参数。
然后,调用调用Get函数就可以取出一个对象,调用Put函数就可以将对象归还到池子中。

4.相关的数据结构

type Pool struct {
    noCopy noCopy //不允许复制
    local    unsafe.Pointer // 指向一个poolLocal类型的变量
    localSize uintptr        // size of the local array
    victim    unsafe.Pointer // local from previous cycle
    victimSize uintptr        // size of victims array
   
    New func() interface{}
}
type poolLocal struct {
    poolLocalInternal

    // Prevents false sharing on widespread platforms with
    // 128 mod (cache line size) = 0 .
    pad [128 - unsafe.Sizeof(poolLocalInternal{})%128]byte
}
// Local per-P Pool appendix.
type poolLocalInternal struct {
    private interface{} // Can be used only by the respective P.
    shared  poolChain   // Local P can pushHead/popHead; any P can popTail.
}

你可能感兴趣的:(golang sync.Pool的用法及实现)