Search code examples
c++multithreading

Is thread A guaranteed to finally see a change from thread B in a infinite loop without synchronization?


Supposing I have an unsynchronized atomic flag is_finished. In the following code:

// thread A
while(!is_finished.test(memory_order_relaxed)) {
    // supposing I have some observable side effects here
}
// thread B
is_finished.test_and_set(memory_order_relaxed);

If these two threads run concurrently, will thread A always end?


Solution

  • The C++ standard does not guarantee that thread A will see the side effects caused by thread B within any particular amount of time. However, on all real hardware, thread A should see the side effects caused by thread B without undue delay. The standard does say that an implementation "should" ensure that thread A will see the side effect "in a finite period of time", which doesn't actually mean anything, since all time is finite in the real world.

    Whether or not you use relaxed memory order makes no difference. The point is that thread A is not going to wake up right away: it will be scheduled whenever the operating system feels like scheduling it. Even if thread A is explicitly waiting on the atomic flag (using the wait member) and thread B notifies all waiters (using the notify member), you still don't know that the operating system is going to wake up thread A right away. A higher-priority task could intervene.

    This is why all guarantees provided by the concept of synchronizes with in the standard are conditional: if thread A sees a side effect caused by thread B and the two operations synchronize, then subsequent operations in thread A are guaranteed to also see previous side effects caused by thread B.