在阅读 Go 的源代码时,我对 src/sync/once.go 中的代码有疑问:
func (o *Once) Do(f func()) {
// Note: Here is an incorrect implementation of Do:
//
// if atomic.CompareAndSwapUint32(&o.done, 0, 1) {
// f()
// }
//
// Do guarantees that when it returns, f has finished.
// This implementation would not implement that guarantee:
// given two simultaneous calls, the winner of the cas would
// call f, and the second would return immediately, without
// waiting for the first's call to f to complete.
// This is why the slow path falls back to a mutex, and why
// the atomic.StoreUint32 must be delayed until after f returns.
if atomic.LoadUint32(&o.done) == 0 {
// Outlined slow-path to allow inlining of the fast-path.
o.doSlow(f)
}
}
func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
为什么使用,而不是说?这些不是等价的吗?有什么区别?atomic.StoreUint32o.done = 1
我们是否必须使用原子运算()来确保其他goroutines可以在内存较弱的机器上观察到之前设置为1的效果?atomic.StoreUint32f()o.done
POPMUISE
泛舟湖上清波郎朗
慕标5832272
相关分类