Go代码全局指针指向局部变量、多线程安全等问题咨询
相关代码
var timePointer *[]time.Time func UpdateHolidayList() error { // 更新逻辑:从API拉取假期列表 holidaySlice := make([]time.Time, 0) // 向holidaySlice追加若干time.Time类型的假期数据 // 此时holidaySlice已包含有效假期数据 timePointer = &holidaySlice return nil } func main() { // 每7天执行一次UpdateHolidayList go func() { for { UpdateHolidayList() // 注:原代码7*3600*time.Hour为笔误,7天对应时长应为7*24*time.Hour time.Sleep(7 * 24 * time.Hour) } }() }
问题解答
将全局指针指向局部变量holidaySlice是否安全?
是安全的。Go语言的逃逸分析会识别到局部变量holidaySlice被外部指针引用,会自动将其分配到堆内存而非函数栈内存,函数退出时holidaySlice占用的内存不会被回收,不会出现悬垂指针问题。整段代码是否具备多线程安全性?
不具备多线程安全性。全局指针timePointer的读写没有加任何同步机制:后台goroutine更新timePointer的值时,如果有其他goroutine同时读取timePointer,会触发数据竞争,轻则读到过期的指针值,重则出现不可预期的程序错误。Go内存模型不保证无同步操作下跨goroutine的变量可见性,即便是机器字长的指针赋值也不能保证原子可见。是否可以通过timePointer正常访问存储的数值?
可以。只要timePointer没有被赋值为nil,解引用后即可拿到对应的切片,正常访问切片内存储的time.Time元素。后续更新holidaySlice后,通过timePointer访问的数值是否会同步变更?
分两种情况:
- 如果你每次访问都是实时解引用最新的
*timePointer,那么拿到的永远是最近一次更新后的假期数据,会同步变更。 - 如果你之前已经把
*timePointer赋值给了另一个切片变量做缓存,那么这个缓存的切片指向的是旧的底层数组,不会随后续更新自动变更,需要重新读取*timePointer才能拿到最新数据。
内容的提问来源于stack exchange,提问作者Mydrive1997
相关产品推荐
相关产品推荐

