11

There are already a few questions on Stackoverflow that essentially ask about the use cases of memory_order_relaxed, such as:

Understanding memory_order_relaxed

What are some use cases for memory_order_relaxed

However, I'm still confused about the precise semantics of memory_order_relaxed. Generally, the example use case for memory_order_relaxed is something like std::shared_ptr - basically it keeps an atomic counter, but it doesn't need to sync with other threads.

Okay, so my understanding is as follows:

std::memory_order_relaxed, when used with load() only guarantees that the thread which loads it will do so atomically - it makes no guarantee about any orderings with respect to other threads that do store() operations on the same variable, and it makes absolutely no guarantee about any loads/stores of non-atomic variables (i.e. no memory fence will be generated.)

But does memory_order_relaxed provide ANY sort of "happens-before" type ordering ability, with regard only to the single atomic value? For example, if we have:

std::atomic_flag x = ATOMIC_FLAG_INIT;

// Thread A:
//
if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread A got here first!" << std::endl;
}

// Thread B:
//
if (!x.test_and_set(std::memory_order_relaxed)) {
   std::cout << "Thread B got here first!" << std::endl;
}

In the above example, even though we used memory_order_relaxed, haven't we also provided a guaranteed way to reason about ordering here? In other words, both Thread A and Thread B will be able to reason about which thread set the flag first. It's just that, due to the relaxed ordering, neither thread A nor thread B will be able to assume anything about the values of any surrounding non-atomic shared variables, since there is no memory fence. Or am I incorrect here?

Community
  • 1
  • 1
Siler
  • 8,976
  • 11
  • 64
  • 124
  • 1
    `test_and_set` is read-modify-write operation, and as I understand when it succeeds - it always acts on "last" value, i.e. only one thread will change it from "0" to "1" . So perhaps you should use other example. Also refer slide 14 [here](https://www.justsoftwaresolutions.co.uk//files/safety_off.pdf). – Evgeny Panasyuk Jul 02 '15 at 18:54
  • Two threads can change it from "0" to "1". Another thread might be clearing it. But I agree that an increment would have been a better example. – David Schwartz Jul 02 '15 at 18:55
  • @DavidSchwartz Of course, but not in this case - there is no `clear`. – Evgeny Panasyuk Jul 02 '15 at 18:56

1 Answers1

8

You're correct. And as you noted, there are use cases (such as a counter) where that's fine.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278