Search code examples
c++multithreadingc++11interruptatomic

Are std::atomic loads and stores both required?


According to this article:

Any time two threads operate on a shared variable concurrently, and one of those operations performs a write, both threads must use atomic operations.

However, if a lower-priority thread is the writer, and a higher-priority thread is the reader, does the lower-priority thread need to enforce atomic stores? It seems to me that only the higher-priority thread needs to enforce an atomic load:

#include <atomic>

std::atomic<T*> ptr; // assume initialized to some non-null value

void highPriThreadFcn(void)
{
    T* local_ptr = ptr.load(); // need atomic load here in case lowPriThread write/store was interrupted
}

void lowPriThreadFcn(T* some_ptr)
{
    ptr = some_ptr; // do I need an atomic store here? I'd think not, as ptr is not written to by highPriThread
}

A similar question would apply in the "reverse" case (write in high-priority thread, read from low-priority thread):

void highPriThreadFcn(T* some_ptr)
{
    ptr = some_ptr; // do I need an atomic store here? I'd think not, as write to ptr cannot be interrupted
}

void lowPriThreadFcn(void)
{
    T* local_ptr = ptr.load(); // need atomic load here in case read/load was interrupted
}

Solution

  • You cannot perform a non-atomic store or load on an atomic variable. The API ensures that there is no way to attempt it. Your allegedly "non-atomic store",

    ptr = some_ptr;
    

    is actually an atomic store with sequentially consistent ordering. See atomic::operator= on cppreference.

    By the way, in case you were thinking about changing the atomic variable to a non-atomic variable on which only some operations are performed atomically: don't do that. Whenever a load and a store to the same memory location are "potentially concurrent", the standard requires that they both be atomic. Otherwise, the behaviour is undefined. That means the compiler is allowed to "optimize" in a way that breaks your code. Whether or not a thread is "higher" priority than another doesn't affect this.