"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Why does sync.Once use atomic.StoreUint32 instead of a standard assignment?

Why does sync.Once use atomic.StoreUint32 instead of a standard assignment?

Published on 2024-11-07
Browse:654

Why does sync.Once use atomic.StoreUint32 instead of a standard assignment?

Atomic Memory Ordering in sync.Once

While exploring the source code of sync.Once, we stumble upon the reasoning behind using atomic.StoreUint32 instead of a standard assignment like o.done = 1.

Memory Ordering in Go

A fundamental concept in concurrent programming is memory ordering, which ensures that shared memory accesses are observed consistently across all processors. However, different architectures implement memory ordering differently, posing challenges for programmers.

Go addresses this by providing a uniform memory model, enforcing a relaxed but consistent memory ordering. All memory accesses are assumed to be asynchronous, with no guarantees of atomicity or ordering.

Atomic Operations in sync.Once

Despite the relaxed memory model, Go mandates the use of atomic operations for shared memory accesses to guarantee correctness across all supported architectures. In sync.Once, atomic.StoreUint32 is employed to safely update the done flag, ensuring that other goroutines can observe the effect of f() before the flag is set to 1.

Fast Path Optimization

atomic.StoreUint32 is utilized in the fast path of sync.Once to optimize performance while maintaining safety. The done flag is checked first with atomic.LoadUint32 and then written with atomic.StoreUint32 because reading the flag concurrently with writes is a data race.

Mutex Protection

The mutex used in doSlow serves to protect the done flag from concurrent writes. The flag can still be read without the mutex because it is a read operation, but concurrent writes must be synchronized to prevent data corruption.

In summary, the use of atomic.StoreUint32 in sync.Once is a consequence of Go's relaxed memory model and the necessity to guarantee thread safety on all supported architectures. By employing atomic operations, sync.Once can safely coordinate concurrent access to shared memory while optimizing performance in the fast path.

Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3