What is the performance of stdatomic vs non-atomic variables?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
When dealing with concurrent programming in C++, one frequently encounters the dilemma of choosing between std::atomic
variables and ordinary non-atomic variables for maintaining shared state between multiple threads. Both have their distinct applications, and understanding their performance implications is crucial. This article delves into the differences in performance between these two types of variables, providing technical explanations and examples.
Understanding std::atomic
std::atomic
is a template class in the C++ Standard Library that provides atomic operations on a single variable. Atomic operations are operations that complete in a single step relative to other threads, essentially making them indivisible. When a thread performs an atomic operation, it's guaranteed that no other thread will be able to see the operation half-complete.
Key Features of std::atomic
- Atomicity: Ensures that operations on variables are completed in a single step.
- Memory Ordering: Provides memory order options to control the visibility and ordering of operations.
- Lock-free Programming: Often implemented using lock-free constructs, providing efficiency advantages.
Non-Atomic Variables
Non-atomic variables (regular variables) do not have the atomicity guarantees that std::atomic
provides. In a multithreaded environment, accessing or modifying these variables without proper synchronization can lead to race conditions, where the behavior depends on the sequence or timing of the threads' execution.
Performance Comparison
The performance difference between std::atomic
and non-atomic variables primarily boils down to the overhead of ensuring atomicity and synchronization versus the simplicity of unsynchronized access.
Example Scenario
Consider the following simplified scenario where a counter variable is accessed by multiple threads.
- Execution Time: Atomic operations are generally slower than non-atomic operations due to the overhead of ensuring atomicity. This involves complex processor instructions and memory fencing, which can slow down execution.
- Thread Synchronization:
std::atomicnaturally provides a means to prevent data races, whereas non-atomic variables would require explicit locking mechanisms such as mutexes, which could introduce even more overhead if not used correctly. - std::memory_order_relaxed: No synchronization, only atomicity.
- std::memory_order_acquire/release: Ensures that memory operations before acquire are visible after release.
- std::memory_order_seq_cst: The strictest, providing a total order.
Related reading
- What is the performance penalty of C11 thread_local variables in GCC 4.8?
- What is the problem name for Traveling salesman problemTSP without considering going back to starting point?
- What is the proper use of Tensorflow dataset prefetch and cache options?
- What is the proper way to benchmark part of tensorflow graph?
- What is the preferred method of running background tasks in IsolatedAsyncioTestCase?
- What is the purpose of CompletableFuture's complete method?
- What is the relationship between BoostAsio and C20 coroutines?
- What is the right approach when using STL container for median calculation?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.