I came across the function InterlockedExchange and was wondering when I should use this function. In my opinion, setting a 32 Bit value on an x86 processor should always be atomic?
In the case where I want to use the function, the new value does not depend on the old value (it is not an increment operation).
Could you provide an example where this method is mandatory (I'm not looking for InterlockedCompareExchange)

- 1,880
- 1
- 25
- 33
7 Answers
InterlockedExchange
is both a write and a read -- it returns the previous value.
This is necessary to ensure another thread didn't write a different value just after you did. For example, say you're trying to increment a variable. You can read the value, add 1, then set the new value with InterlockedExchange
. The value returned by InterlockedExchange
must match the value you originally read, otherwise another thread probably incremented it at the same time, and you need to loop around and try again.

- 81,399
- 26
- 107
- 114
-
4In this case, I would use InterlockedCompareExchange, because the check whether the value was still the original one is done by the method already. – EFrank Oct 16 '08 at 14:00
As well as writing the new value, InterlockedExchange
also reads and returns the previous value; this whole operation is atomic. This is useful for lock-free algorithms.
(Incidentally, 32-bit writes are not guaranteed to be atomic. Consider the case where the write is unaligned and straddles a cache boundary, for instance.)

- 86,889
- 7
- 82
- 122
-
It would be atomic from the standpoint of software running on the processor, but not from the standpoint of hardware sitting on the bus. – Brian Knoblauch Oct 16 '08 at 13:36
-
1Would it be atomic from the POV of software running on another core? What about a write that straddles a page boundary and triggers a fault? It's been years since I did any low-level x86 coding, guess I may be lying :/ – moonshadow Oct 16 '08 at 14:10
In a multi-processor or multi-core machine each core has it's own cache - so each core has each own potentially different "view" of what the content of the system memory is.
Thread synchronization mechanisms take care of synchronizing between cores, for more information look at http://blogs.msdn.com/oldnewthing/archive/2008/10/03/8969397.aspx or google for acquire and release semantics

- 29,306
- 10
- 67
- 103
-
2Caches are secondary here. Even if there are no caches and CPUs were talking to memory directly normal read / write sequence is not atomic. – Suma Jun 08 '10 at 12:34
Setting a 32-bit value is atomic, but only if you're setting a literal.
b = a is 2 operations:
mov eax,dword ptr [a]
mov dword ptr [b],eax
Theoretically there could be some interruption between the first and second operation.

- 23,011
- 10
- 73
- 102
-
4And if there would be some interruption, then what - it will take a little bit longer, but the value in eax will not change. The real point of InterlockedExchange is that it is atomic read and write. – Suma Jun 08 '10 at 12:33
-
2Then what? Hell. The interrupt can cause a system call, the system call a context switch and then another thread changes the value. Then EAX is restored and the value is changed again. Race conditions are especially fatal when counting references. Some thread may increment the value while another thread decrements the value, or two threads may increment it at the same time. That EAX is restored is not the solution - its the problem. – Andreas Spindler Aug 28 '13 at 08:45
-
-
1Nothing serious in this case. `b` will be written with a single instruction regardless of its previous value. – Fr0sT Sep 16 '16 at 08:18
Writing a value is never atomic by default. When you write a value to a variable, several machine instructions are generated. With modern, preemptive OSes, the OS might switch to another thread between the individual operations of the write.
This is even more a problem on multi-processor machines, where several threads could be executing at the same time, and trying to write to a single memory location simultaneously.
Interlocked operations avoid this by using specialized instructions to make the write (x86 has dedicated instructions for this kind of situation), which do the read-modify-write in one instruction. These instructions also lock the memory bus of all processors, to ensure that no other executing thread could be writing to the value at the same time.

- 1,589
- 1
- 13
- 18
InterlockedExchange makes sure that the change of a variable and the return of its original value are not interrupted by other threads.
So, if 'i' is an int, these calls (taken individually) do not need InterlockedExchange around 'i':
a = i;
i = 9;
i = a;
i = a + 9;
a = i + 9;
if(0 == i)
None of these statements rely upon BOTH the initial AND final values of 'i'. But these following calls DO need InterlockedExchange around 'i':
a = i++; //a = InterlockedExchange(&i, i + 1);
Without it, two threads running through this same code might get the same value of 'i' assigned to 'a' or 'a' may unexpectedly skip two or more numbers.
if(0 == i++) //if(0 == InterlockedExchange(&i, i + 1))
Two threads may both execute the code that is only supposed to happen once.
etc.

- 29
- 1
-
Incorrect example `a = InterlockedExchange(&i, i + 1);`. Your `i` might be changed by the other CPU between `i + 1` and `InterlockedExchange`. – Fr0sT Sep 16 '16 at 08:14
wow, so many conflicting answers. Hard to sift through who's right, who's wrong, and what information is misleading.
I'm unsure of the answer too, given the above half-answers, but I think it works like this, I may be wrong, and it will be interesting to find out if I am:
- 32-bit read & writes ARE atomic, but depending on your code, that may not mean much.
- don't worry about non-aligned read/writes. ALL 32-bit writes to a 32-bit variable have to be aligned or the machine page-faults.
- don't worry about a write wrapping around the end of a cached page, that can't happen.
- If you need to write-then-read on one thread, and you're writing on another thread, then you need to use InterlockedExchange. If you're simply reading the value on one thread, and writing it on another, then you don't need to use it, but those values may be wiggly because of multithreading.

- 47
- 4
-
-1 32-bits vars need not be aligned on x86. And 32bit writes are atomic on x86, but not on many other architectures. – Johan Sep 19 '14 at 21:04