Skip to content

Std::atomic

Memory order

Used as an argument to functions that conduct atomic operations to specify how other operations on different threads are synchronized.

std::memory_order specifies how regular, non-atomic memory accesses are to be ordered around an atomic operation. Absent any constraints on a multi-core system, when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads. Some similar effects can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.

The default behavior of all atomic operations in the library provides for sequentially consistent ordering (see discussion below). That default can hurt performance, but the library's atomic operations can be given an additional std::memory_order argument to specify the exact constraints, beyond atomicity, that the compiler and processor must enforce for that operation.

compare_exchange_weak & compare_exchange_strong

비교하여, 정확하다면 값을 적용한다.

Parameters

expected
객체에서 예상되는 값의 참조형. (즉, 비교할 값)
desired
expected값이 atomic object의 값과 동일하다면 저장할 값.
success
the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
failure
the memory synchronization ordering for the load operation if the comparison fails. Cannot be std::memory_order_release or std::memory_order_acq_rel and cannot specify stronger ordering than success (until C++17)
order
the memory synchronization ordering for both operations

Return value

값이 정상적으로 변경되었다면 true, 그 밖의 경우는 false를 반환한다.

atomic_thread_fence

Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, without an associated atomic operation.

atomic_signal_fence

Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, between a thread and a signal handler executed on the same thread. This is equivalent to std::atomic_thread_fence, except no CPU instructions for memory ordering are issued. Only reordering of the instructions by the compiler is suppressed as order instructs. For example, a fence with release semantics prevents reads or writes from being moved past subsequent writes and a fence with acquire semantics prevents reads or writes from being moved ahead of preceding reads.

acquire / release

atomic_bool vs atomic_flag

std::atomic bool type not guranteed to be lock-free?

Correct. std::atomic may be implemented using locks.

then it's not atomic or what?

std::atomic is atomic whether it has been implemented using locks, or without. std::atomic_flag is guaranteed to be implemented without using locks.

So what's the difference b/w two

The primary difference besides the lock-free guarantee is:

std::atomic_flag does not provide load or store operations.
and when should I use which?

Usually, you will want to use std::atomic<bool> when you need an atomic boolean variable. std::atomic_flag is a low level structure that can be used to implement custom atomic structures.

Troubleshooting

Does std::atomic<std::string> work appropriately?

Undefined reference atomic

특정 크기이상의 Trivial type을 Atomic 템플릿 인자로 전달할 경우 아래와 같은 링커 에러가 발생될 수 있다.

/tmp/cc8gyaZM.o: In function `std::atomic<A>::store(A, std::memory_order)':
dryn.cpp:     (.text._ZNSt6atomicI1AE5storeES0_St12memory_order[_ZNSt6atomicI1AE5storeES0_St12memory_order]+0x3e): undefined reference to `__atomic_store_16'

Atomic API isn't complete in GCC 4.7:

When lock free instructions are not available (either through hardware or OS support) atomic operations are left as function calls to be resolved by a library. Due to time constraints and an API which is not finalized, there is no libatomic supplied with GCC 4.7. This is easily determined by encountering unsatisfied external symbols beginning with __atomic_*.

Since there is no libatomic shipped with GCC 4.7 you need to use another compiler which actually supports the features you want or provide the missing features (sample implementation).

한마디로 링커에 atomic 라이브러리를 아래와 같이 추가해야 한다.

-latomic

Libraries

See also

Favorite site

Atomic pointer

How to use

memory order

References


  1. Std_memory_order_-_cppreference.pdf 

  2. Findessentials_-_acquire_and_release_fence.pdf 

  3. Egloos_zum_com-sweeper-c++11_std_atomic.pdf 

  4. Concurrency-in-action-chapter-5.tar.gz