I have read the article Synchronization and Multiprocessor Issues and I have a question about InterlockedCompareExchange and InterlockedExchange. The question is actually about the last example in the article. They have two variables iValue
and fValueHasBeenComputed
and in CacheComputedValue()
they modify each of them using InterlockedExchange
:
InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue()); // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
I understand that I can use InterlockedExchange
for modifing iValue
but is it enought just to do
iValue = ComputeValue();
So is it actually necessary to use InterlockedExchange
to set iValue? Or other threads will see iValue correctly even if iValue = ComputeValue();
. I mean the other threads will see iValue correctly because there is InterlockedExchange
after it.
There is also the paper A Principle-Based Sequential Memory Model for Microsoft Native Code Platforms. There is the 3.1.1 example with more or less the same code. One of the recomendation Make y interlocked
. Notice - not both y
and x
.
Update
Just to clarify the question. The issue is that I see a contradiction. The example from "Synchronization and Multiprocessor Issues" uses two InterlockedExchange
. On the contrary, in the example 3.1.1 "Basic Reodering" (which I think is quite similar to the first example) Herb Sutter gives this recomendation
"Make y interlocked: If y is interlocked, then there is no race on y because it is atomically updatable,and there is no race on x because a -> b -> d."
. In this draft Herb do not use two interlocked variable (If I am right he means use InterlockedExchange
only for y
).
fValueHasBeenComputed
need to be interlocked. Why did they make it like this, I don't know. – GrammariValue
would be updated atomically (unless your code does something horrible to break alignment). So instructions in another thread have nothing to do with it. Morover, even when both variables are updated with interlocked operations, there's still an interval in between them where instructions in another thread will see the nerw value ofiValue
and the old value offValueHasBeenComputed
. So the race condition is still there with interlocked. – OntineCacheComputedValue()
. However, races betweenCache...
andFetch...
are equally impossible in both. Arguing forInterlockedExchange
(especially if you don't use its return value) on grounds of race condition is lame. – GrammarInterlocked...
doesn't solve this either. – GrammarLONG
on x86 (using Win32's definition ofLONG
) will (assuming your data is well aligned) be atomic. And no matter how many interlocked operations you use, there will be a gap betweeniValue
andfValueHasBeenComputed
getting updated, so there will be a potential race condition there if other code assumes that the two variables will be updated as a single atomic operation. – Ontine