Atomic.StoreUint32 vs. Normal Assignment in Sync.Once
In the context of Go's sync.Once, the atomic.StoreUint32 operation is preferred over a normal assignment for setting the done field to 1. This preference stems from the specific semantics and guarantees provided by sync.Once.
Guarantees of Sync.Once
Sync.Once ensures that the function passed to the Do method executes only once. To maintain this guarantee, the done field, which indicates whether the function has already been executed, must be atomically updated.
Limitations of Normal Assignment
If a normal assignment were used (equivalent to o.done = 1), this guarantee could not be assured on architectures with weak memory models. On such architectures, changes made by one goroutine may not be immediately visible to other goroutines, which could lead to multiple goroutines invoking the function in violation of the once-only execution requirement.
Atomic.StoreUint32 Operation
atomic.StoreUint32 is an atomic operation that ensures visibility of the write across all goroutines. By using it to set the done field, sync.Once ensures that all goroutines observe the effect of the function execution before it marks the function as complete.
Scope of Atomic Operations
It's important to note that the atomic operations used in sync.Once are primarily for optimizing the fast path. Access to the done flag outside the mutex synchronized via o.m.Lock() and o.m.Unlock() only needs to be safe, not strictly ordered. This optimization allows for efficient execution on hot paths without sacrificing correctness.
Concurrent Access Considerations
Even though the function execution is protected by the mutex, reading the done field is a data race. Consequently, atomic.LoadUint32 is used to read the field to ensure correct visibility. Likewise, atomic.StoreUint32 is employed to update the field after the function execution, guaranteeing that other goroutines observe the completion of the function before the done flag is set.
In summary, atomic.StoreUint32 is preferred over normal assignment in sync.Once to maintain the guarantee that the function executes only once, even on architectures with weak memory models, due to the atomic visibility it provides. This optimization is applied to enhance performance on the fast path.
The above is the detailed content of Why is `atomic.StoreUint32` Preferred over Normal Assignment in `sync.Once`?. For more information, please follow other related articles on the PHP Chinese website!