There are definitely plenty of pitfalls with atomics. C/C++ also definitely give you all the tools you need to get into trouble with e.g., relaxed atomics.
But even 'relaxed' has its justification sometimes.
And you can't really use them without knowing what types are lock free on your platform.
You can, however, test if a particular atomic type is lock-free, using atomic_is_lock_free() and the ATOMIC_XXX_LOCK_FREE macros in C. In C++ there is also std::atomic<T>::is_always_lock_free, which is constexpr.
In C or C++, the primary meaning of 'atomic' is 'atomic with regard to other threads'. This does not require lock-freeness, but it can be achieved with locks as well.
A different (or additional) aspect is asynchronous signal safety, and it is only guaranteed for lock-free atomic data types; in other words, only lock-free atomic data types can be safely manipulated in signal or interrupt handlers.
But for simple uses like an atomic flag they mostly work.
In fact, atomic_flag is the only atomic type which is always guaranteed to be lock-free (on every platform that supports stdatomic).