Trying to understand the relation between Thread.MemoryBarrier() and context switching
-
17-01-2021 - |
Question
Since it appears that context switch may happen at any point in execution of instructions I am now wondering why code "in part in question" (those 2 instructions) makes sense, if context switch can happen between any instructions and we may be on different CPU core in second instruction.
void B()
{
Thread.MemoryBarrier(); // Barrier 3
if (_complete)
{
//PART IN QUESTION
Thread.MemoryBarrier(); // Barrier 4
Console.WriteLine (_answer);
//END PART IN QUESTION
}
}
Description on MemoryBarrier here doesn't appear to give guarantees MemoryBarrier that CPUs won't be switched after calling it.
(this is related to this question)
Solution
What guarantees that context-switch will not happen after Thread.MemorryBarrier() call?
Nothing. MemoryBarriers does not prevent context switching, (or atomic execution of your code).
As to your other question, why Barrier 4 is needed:
In the example code from the previous question, the C# compiler, CLR or the CPU might reorder reading of the answer variable before the completed variable if barrier 4 was not there. i.e. the code that actually runs could be similar to:
Thread.MemoryBarrier(); // Barrier 3
int tmpanswer = _answer;
if (_complete)
{
Console.WriteLine (tmpanswer);
}
A barrier before the Console.WriteLine() will prevent reading _answer
before reading _completed
But keep in mind that the code example only provides this one guarantee about the code in void B() (provided A() is run only once )
- If the _complete variable is true , then Console.WriteLine will write out 123 and not 0.
So, unless A and B are run serially, the code does not provide any locking/notification such that B will always print 123. A() and B() could be interleaved/interrupted any time in its execution - you have no control over who gets to run when.
There is no guarantee that B() runs after A(), no matter which order you started the 2 threads in. (Though somewhere else in the code , you could start A() first and wait explicitly for it to finish before starting B() ofcourse)
OTHER TIPS
There are no guarantees that a context switch will or won't happen around a MemoryBarrier
. These are orthogonal concepts.