# (sync.Pool)[https://github.com/golang/go/blob/go1.22.11/src/sync/pool.go]

# 数据结构

type Pool struct {
	noCopy noCopy
	local     unsafe.Pointer // 指向每个 P(处理器)的本地对象池,实际类型为 [P] poolLocal
	localSize uintptr        //local 数组的大小(即 P 的数量)
	victim     unsafe.Pointer // 指向上一个 GC 周期的本地对象池,用于 GC 回收
	victimSize uintptr        //victim 数组的大小
	// New 可选函数,用于在 Get 返回 nil 时生成新对象
    // 不能与 Get 并发修改
	New func() any
}
//poolLocal 是每个 P 的本地对象池
type poolLocal struct {
	poolLocalInternal
	//pad 字段用于填充内存,防止 false sharing
    // 在主流平台上,使结构体大小为 128 字节的整数倍
    // 这样可以确保不同 P 的 poolLocal 位于不同的缓存行,避免缓存失效
	pad [128 - unsafe.Sizeof(poolLocalInternal{})%128]byte
}
//poolLocalInternal 每个 P(处理器)专属的对象池内部结构
type poolLocalInternal struct {
	private any       //private 只能被对应的 P 使用,用于快速访问
	shared  poolChain //shared 是一个共享队列,本地 P 可以在队首进行 push/pop 操作,其他 P 可以从队尾 pop
}
//poolChain 实现了一个双向链表结构的对象池队列
type poolChain struct {
	//head 指向用于 push 操作的 poolDequeue
	// 只被生产者访问,因此不需要同步
	head *poolChainElt
	//tail 指向用于 popTail 操作的 poolDequeue
    // 被消费者访问,因此读写必须是原子操作
	tail *poolChainElt
}
//poolChainElt 是 poolChain 中的链表节点
type poolChainElt struct {
    poolDequeue // 嵌入 poolDequeue 实现底层的队列功能
    //next 和 prev 指向 poolChain 中相邻的节点
    //
    //next 由生产者原子写入,由消费者原子读取
    // 只能从 nil 变为非 nil
    //
    //prev 由消费者原子写入,由生产者原子读取
    // 只能从非 nil 变为 nil
    next, prev *poolChainElt
}
//poolDequeue 实现了一个无锁循环队列
type poolDequeue struct {
    headTail atomic.Uint64 // 使用一个 64 位整数同时存储队列的头尾指针
                          // 高 32 位存储 head,低 32 位存储 tail
    vals []eface // 存储对象的底层数组,使用 eface 接口类型表示任意对象
}
//eface 表示一个空接口,用于存储任意类型的对象
type eface struct {
    typ unsafe.Pointer // 指向类型信息的指针
    val unsafe.Pointer // 指向实际数据的指针
}

# Get 操作

func (p *Pool) Get() any {
	
	// 
	l, pid := p.pin()
	x := l.private
	l.private = nil
	if x == nil {
		// Try to pop the head of the local shard. We prefer
		// the head over the tail for temporal locality of
		// reuse.
		x, _ = l.shared.popHead()
		if x == nil {
			x = p.getSlow(pid)
		}
	}
	runtime_procUnpin()
	if race.Enabled {
		race.Enable()
		if x != nil {
			race.Acquire(poolRaceAddr(x))
		}
	}
	if x == nil && p.New != nil {
		x = p.New()
	}
	return x
}

# Put 操作

func (p *Pool) Put(x any) {
	if x == nil {
		return
	}
	if race.Enabled {
		if runtime_randn(4) == 0 {
			// Randomly drop x on floor.
			return
		}
		race.ReleaseMerge(poolRaceAddr(x))
		race.Disable()
	}
	l, _ := p.pin()
	if l.private == nil {
		l.private = x
	} else {
		l.shared.pushHead(x)
	}
	runtime_procUnpin()
	if race.Enabled {
		race.Enable()
	}
}
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ZJM 微信支付

微信支付

ZJM 支付宝

支付宝