golang sync.Pool 指针数据覆盖问题

场景

  1. sync.Pool设置
Go 复制代码
var stringPool = sync.Pool{
	New: func() any {
		return new([]string)
	},
}

func NewString() *[]string {
	v := stringPool.Get().(*[]string)
	return v
}

func PutString(s *[]string) {
	if s == nil {
		return
	}

	if cap(*s) > 2048 {
		s = nil
	} else {
		*s = (*s)[:0]
		stringPool.Put(s)
	}
}

2.使用sync.Pool

Go 复制代码
func Test_Pool(t *testing.T) {
	dataSlice1 := demoData()
	dataSlice2 := demoData()
	dataSlice2[1] = "test4"

	fmt.Printf("dataSlice1:%v %p,dataSlice2:%v %p\n", dataSlice1, dataSlice1, dataSlice2, dataSlice2)
}

func demoData() []string {
	strsPtr := NewString()
	strs := *strsPtr
	defer func() {
		*strsPtr = strs
		PutString(strsPtr)
	}()

	strs = append(strs, "test1", "test2")
	return strs
}

打印结果:dataSlice1:test1 test4 0xc0000a6400,dataSlice2:test1 test4 0xc0000a6400

可以看到两个slice地址相同,内部使用同一个地址的数组,导致两次获取的数据互相影响

3.解决方法1

Go 复制代码
func Test_Pool(t *testing.T) {
	dataSlice1 := demoData()
	dataSlice2 := demoData()
	dataSlice2[1] = "test4"

	fmt.Printf("dataSlice1:%v %p,dataSlice2:%v %p\n", dataSlice1, dataSlice1, dataSlice2, dataSlice2)
}

func demoData() []string {
	strsPtr := NewString()
	strs := *strsPtr
	defer func() {
		*strsPtr = strs
		PutString(strsPtr)
	}()

	strs = append(strs, "test1", "test2")

	// 深复制
	var items = make([]string, len(strs))
	copy(items, strs)

	return items
}

使用深复制,在put回sync.Pool中之前把数据复制返回,但这样资源池失去了意义,获取到资源后有进行了一次内存的申请

4.解决方法2

我们看下golang语言源码怎么解决的

参考 go/src/fmt/print.go 302行 Fprintln方法

Go 复制代码
func Fprintln(w io.Writer, a ...any) (n int, err error) {
	p := newPrinter()
	p.doPrintln(a)
	n, err = w.Write(p.buf)
	p.free()
	return
}

可以看到306行有p.free()代码,newPrinter()和free()之间进行数据处理,数据处理完成之后再把资源返回给sync.Pool

总结:不是任何场景都适合用sync.Pool,需要关注并发情况下资源池中数据同步修改影响的问题。

相关推荐
kimnoic5 小时前
Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点
开发语言·python
架构技术专栏5 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
码事漫谈5 小时前
你让AI干的活,它可能只干了十分之一——而你根本看不出来
后端
必须得开心呀6 小时前
python编写带界面的软件,需要安装哪些插件
开发语言·python
Wx-bishekaifayuan6 小时前
express皖美特色农产品网售系统53118-计算机课程设计、毕业设计
人工智能·spring boot·后端·python·课程设计·express·旅游
Wx-bishekaifayuan6 小时前
springboot汉中旅游服务平台41442-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
WeiXin_DZbishe7 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
WeiXin_DZbishe7 小时前
基于Springboot+AI的kuall音乐广场的设计与实现-计算机毕设 附源码【课程设计】12715
vue.js·人工智能·spring boot·后端·python·php·课程设计
A接拉起0077 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
Bazingga8 小时前
RAG评测体系保姆级教程:生产级实践指南
后端