I'm reading this article, and I follow the author's steps but get a different result.
I create two threads. One is reader, and one is writer.
// volatile uint64_t variable1 = 0; <- global
// uint64_t* variable2_p = new uint64_t(0); <- in main function
// const unsigned ITERATIONS = 2000000000; <- global
void *reader(void *variable2) {
volatile uint64_t *variable2_p = (uint64_t *)variable2;
// bind this thread to CPU0
unsigned i, failureCount = 0;
for (i=0; i < ITERATIONS; i++) {
uint64_t v2 = *variable2_p;
uint64_t v1 = variable1;
if (v2 > v1) {
failureCount++;
printf("v1:%" PRIu64 ", v2:%" PRIu64 "\n", v1, v2);
}
}
printf("%u failure(s)", failureCount);
return NULL;
}
void *writer(void *variable2) {
volatile uint64_t *variable2_p = (uint64_t *)variable2;
// bind this thread to CPU1
for (;;) {
variable1 = variable1 + 1;
*variable2_p = (*variable2_p) + 1;
}
return NULL;
}
In the article above, the author said that the compare v2 <= v1
may fail for some time because the compiler or the processor may change the execution order.
But I tried so many times, there isn't any failure cases. I'm confused that is that right to use only volatile
is this situation? Or it will lead to some delicate bugs?
If it isn't OK, please give me a example. Thanks a lot.
compile command: g++ -O2 -Wall -g -o foo foo.cc -lpthread
uname -a: Linux Wichmann 3.5.0-48-generic #72~precise1-Ubuntu SMP Tue Mar 11 20:09:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
cpuid: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz