No, it is not. The test_and_set() operation itself is atomic, so it doesnβt matter how deep the call stacks of different threads are.
To demonstrate this, consider the basic case where the atomic_flag object atomic_flag "open":
static atomic_flag flag = ATOMIC_FLAG_INIT; void threadMethod() { bool wasFirst = !flag.test_and_set(); if( wasFirst ) cout << "I am thread " << this_thread::get_id() << ", I was first!" << endl; else cout << "I am thread " << this_thread::get_id() << ", I'm the runner-up" << endl; }
If two threads enter threadMethod - one thread ( t1 ) a bit before the other ( t2 ), then we can expect the console output to be as follows (in the same order):
I am thread t1, I was first! I am thread t2, I'm the runner-up
Now, if both threads enter at the same time, but t2 is the microsecond ahead of t1 , but t2 then becomes slower than t1 , since it writes to stdout, then the output will be:
I am thread t1, I'm the runner-up I am thread t2, I was first!
... therefore the call to test_and_set was still atomic, although the output is not necessarily in the expected order.
Now, if you had to wrap the flag another way (not built-in to be sure), like this ...
__declspec(noinline) bool wrap() { return !flag.test_and_set(); } void threadMethod() { bool wasFirst = wrap(); if( wasFirst ) cout << "I am thread " << this_thread::get_id() << ", I was first!" << endl; else cout << "I am thread " << this_thread::get_id() << ", I'm the runner-up" << endl; }
... then the program will not behave differently - because the value false or true return bool from test_and_set() will still be in each thread stream. Ergo, wrapping a atomic_flag does not change its atomicity.