开发者

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

目录
  • 场景
    • 1. sync.Pool设置
    • 2.使用sync.Pool
    • 3.解决方法1
    • 4.解决方法2
  • 总结

    场景

    1. sync.Pool设置

    var stringPool = sync.Pool{
    	New: func() any {
    		return new([]string)
    	},
    }
    
    func NewString() *[]string {
    	v := stringPool.Get().(*[]string)
    javascript	return v
    }
    
    func PutString(s *[]string) {
    	if s == nil {
    		retuhttp://www.devze.comrn
    	}
    
    	if cap(*s) > 2048 {
    		s = nil
    	} else {
    		*s = (*s)[:0]
    		stringPool.Put(s)
    	}
    }

    2.使用sync.Pool

    func Test_Pool(t *testing.Tjs) {
    	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 demoDjavascriptata() []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,需要关注并发情况下资源池中数据同步修改影响的问题。

    到此这篇关于golang sync.Pool 指针数据覆盖问题解决的文章就介绍到这了,更多相关golang sync.Pool 指针覆盖内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜