Any guideline on which atomic ordering to choose?

In the upcoming Julia@v1.7 Per-field atomics, it mentions several atomic orderings: (:monotonic, :acquire, :release, :acquire_release, or :sequentially_consistent). Do you have any general suggestions for which one to use?

The basic premise is: do not use anything other than std::memory_order_seq_cst (the default) unless (a) you really really know what you are doing, and can prove that the relaxed usage is safe in all cases, and (b) your profiler demonstrates that the data structure and operations you are intending to use the relaxed orderings with are a bottleneck.

Specific details of the memory model and other details of the design are written in the Julia Atomics Manifesto, which will later be published formally.

Julia Atomics Manifesto

These memory orderings can be any of the following symbols. More precise definitions can be found elsewhere (in particular, at, so here we give only the particulars of how they will be mapped inside the Julia runtime.

  • not_atomic: single-threaded usage only, or inside a lock. This is the default behavior for most operations. This cannot be used to down-grade an atomic write, but simply names the default parameterization for a non-atomic access. And when applied to an atomic field, it’ll be automatically upgraded to a monotonic read.
  • monotonic: This ensures atomicity of the operation, but otherwise does not ensure the code makes forward progress (do not use in a loop), but only ensures that the operations are seen monotonically making progress within a thread.
  • acquire: This is an error to specify on a store.
  • release: This is an error to specify on a load.
  • acquire_release: This is an error to specify on an operation that doesn’t both read and write memory (so it’s an error to specify on a load or store, and the release will be ignored for a replacefield! failure).
  • sequentially_consistent: Sequential consistency is the default behavior for @atomic when the ordering is not specified.

The specification and constraints on how these apply to individual operations is particularly nicely described here:

1 Like