Consider the following test program, compiled and run on an implementation that fully implements C2011 atomics and threads.
#include <stdio.h>
#include <stdatomic.h>
#include <threads.h>
#if !ATOMIC_INT_LOCK_FREE
#error "Program behavior is only interesting if atomic_int is lock-free."
#endif
static atomic_int var;
int inc_print(void *unused)
{
atomic_fetch_add(&var, 1);
printf(" %d", atomic_load(&var));
return 0;
}
int main(void)
{
thrd_t thrd;
if (thrd_create(&thrd, inc_print, 0) == thrd_success) {
inc_print(0);
thrd_join(&thrd, 0);
}
putchar('\n');
return 0;
}
I have managed to convince myself that all of the following statements are true:
- Each thread's
atomic_load
must observe the increment performed by that same thread, so it cannot read a zero. - Each thread's
atomic_load
may or may not observe the increment performed by the other thread. (The other thread might not get scheduled at all until after the atomic_load.) Therefore, it can read either a 1 or a 2. - The calls to
printf
are serialized only against each other. Therefore, if one thread'satomic_load
reads a 1 and the other thread'satomic_load
reads a 2, either1 2
or2 1
may be printed. - It is possible for both
atomic_load
s to observe the increment performed by the other thread, so the output2 2
is also possible.
What I'm not sure of, though: Is it possible for neither of the atomic_load
s to observe the increment performed by the other thread? That is, is the output 1 1
possible?
Also, does relaxing the memory model change anything?