Atomic.StoreUint32 与 Sync.Once 中的普通赋值
在 Go 的sync.Once 上下文中,atomic.StoreUint32 操作是优先于将 did 字段设置为 1 的正常分配。此首选项源于sync.Once 提供的特定语义和保证。
Sync.Once 的保证
Sync.Once 确保传递给 Do 方法的函数仅执行一次。为了维持这种保证,必须原子更新表示函数是否已经执行的done字段。
正常赋值的限制
如果正常赋值使用(相当于 o.done = 1),在内存模型较弱的架构上无法保证这一保证。在这样的架构上,一个 goroutine 所做的更改可能不会立即对其他 goroutine 可见,这可能会导致多个 goroutine 调用该函数,违反了一次性执行要求。
Atomic.StoreUint32 操作
atomic.StoreUint32 是一个原子操作,可确保所有 goroutine 中写入的可见性。通过使用它来设置done字段,sync.Once确保所有goroutine在将函数标记为完成之前观察到函数执行的效果。
原子操作的范围
需要注意的是,sync.Once中使用的原子操作主要是为了优化快速路径。通过 o.m.Lock() 和 o.m.Unlock() 同步的互斥体外部的完成标志的访问只需要安全,不需要严格排序。这种优化允许在不牺牲正确性的情况下在热路径上高效执行。
并发访问注意事项
即使函数执行受互斥体保护,读取完成字段也是如此数据竞赛。因此,atomic.LoadUint32 用于读取字段以确保正确的可见性。同样,使用atomic.StoreUint32在函数执行后更新字段,保证其他goroutines在done标志被设置之前观察到函数的完成。
综上所述,atomic.StoreUint32优于普通赋值由于它提供了原子可见性,即使在内存模型较弱的体系结构上,也能保证函数仅执行一次。此优化用于增强快速路径上的性能。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3