golang sync.Pool 指针数据覆盖问题
温馨提示:这篇文章已超过377天没有更新,请注意相关的内容是否还可用!
场景
(图片来源网络,侵删)
1. sync.Pool设置
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
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
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方法
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,需要关注并发情况下资源池中数据同步修改影响的问题。
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
