Go: How to Reduce Lock Contention with the Atomic Package
ℹ️ This article is based on Go 1.14.
Go provides memory synchronization mechanisms such as channel or mutex that help to solve different issues. In the case of shared memory, mutex protects the memory against data races. However, although two mutexes exist, Go also provides atomic memory primitives via the atomic
package to improve performance. Let’s first go back to the data races before diving into the solutions.
Data Race
A data race can occur when two or more goroutines access the same memory location concurrently, and at least one of them is writing. While the maps have a native mechanism to protect against data races, a simple structure does not have any, making it vulnerable to data races.
To illustrate a data race, I will take an example of a configuration that is continuously updated by a goroutine. Here is the code:
Running this code clearly shows that the result is non-deterministic due to the data race:
[...]
&{[79167 79170 79173 79176 79179 79181]}
&{[79216 79219 79220 79221 79222 79223]}
&{[79265 79268 79271 79274 79278 79281]}