func(p *Pool) Get() interface{} { if race.Enabled { race.Disable() } // 获取本地 P 的 poolLocal 对象 l := p.pin() // 先获取 private 池中的对象(只有一个) x := l.private l.private = nil runtime_procUnpin() if x == nil { // 查找本地 shared 池, // 本地 shared 可能会被其他 P 访问 // 需要加锁 l.Lock() last := len(l.shared) - 1 if last >= 0 { x = l.shared[last] l.shared = l.shared[:last] } l.Unlock() // 查找其他 P 的 shared 池 if x == nil { x = p.getSlow() } } if race.Enabled { race.Enable() if x != nil { race.Acquire(poolRaceAddr(x)) } } // 未找到可用元素,调用 New 生成 if x == nil && p.New != nil { x = p.New() } return x }
func(p *Pool) getSlow() (x interface{}) { // See the comment in pin regarding ordering of the loads. size := atomic.LoadUintptr(&p.localSize) // load-acquire local := p.local // load-consume // Try to steal one element from other procs. pid := runtime_procPin() runtime_procUnpin() for i := 0; i < int(size); i++ { l := indexLocal(local, (pid+i+1)%int(size)) // 对应 pool 需加锁 l.Lock() last := len(l.shared) - 1 if last >= 0 { x = l.shared[last] l.shared = l.shared[:last] l.Unlock() break } l.Unlock() } return x }
Put
Put 优先把元素放在 private 池中;如果 private 不为空,则放在 shared 池中。有趣的是,在入池之前,该元素有 1/4 可能被丢掉。
func(p *Pool) Put(x interface{}) { if x == nil { return } if race.Enabled { if fastrand()%4 == 0 { // 随机把元素扔掉... // Randomly drop x on floor. return } race.ReleaseMerge(poolRaceAddr(x)) race.Disable() } l := p.pin() if l.private == nil { l.private = x x = nil } runtime_procUnpin() if x != nil { // 共享池访问,需要加锁 l.Lock() l.shared = append(l.shared, x) l.Unlock() } if race.Enabled { race.Enable() } }