Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need clarification about Thread.MemoryBarrier() [duplicate]

Possible Duplicate:
Why we need Thread.MemoryBarrier()?

From O'Reilly's C# in a Nutshell:

class Foo
{
    int _answer;
    bool _complete;
    void A()
    {
        _answer = 123;
        Thread.MemoryBarrier(); // Barrier 1
        _complete = true;
        Thread.MemoryBarrier(); // Barrier 2
    }
    void B()
    {
        Thread.MemoryBarrier(); // Barrier 3
        if (_complete)
        {
            Thread.MemoryBarrier(); // Barrier 4
            Console.WriteLine (_answer);
        }
    }
}

Suppose methods A and B ran concurrently on different threads:


The author says: "Barriers 1 and 4 prevent this example from writing “0”. Barriers 2 and 3 provide a freshness guarantee: they ensure that if B ran after A, reading _complete would evaluate to true."

My questions are:

  1. Why Barrier 4 is needed ? Barrier 1 isn't enough ?
  2. Why 2 & 3 are needed ?
  3. From what I understand, the barrier prevent executing instructions prior to its location after its following instructions, am I correct ?
like image 257
Tar Avatar asked Oct 14 '25 13:10

Tar


1 Answers

Memory barrier enforces ordering constraint on reads and writes from/to memory: memory access operations before the barrier happen-before the memory access after the barrier.

  1. Barriers 1 and 4 have complementary roles: barrier 1 ensures that the write to _answer happens-before the write to _complete, while barrier 4 ensures that the read from _complete happens-before the read from _answer. Imagine barrier 4 isn't there, but barrier 1 is. While it is guaranteed that 123 is written to _answer before true is written to _complete some other thread running B() may still have its read operations reordered and hence it may read _answer before it reads _complete. Similarly if barrier 1 is removed with barrier 4 kept: while the read from _complete in B() will always happen-before the read from _answer, _complete could still be written to before _answer by some other thread running A().

  2. Barriers 2 and 3 provide freshness guarantee: if barrier 3 is executed after barrier 2 then the state visible to the thread running A() at the point when it executes barrier 2 becomes visible to the thread running B() at the point when it executes barrier 3. In the absence of any of these two barriers B() executing after A() completed might not see the changes made by A(). In particular barrier 2 prevents the value written to _complete from being cached by the processor running A() and forces the processor to write it out to the main memory. Similarly, barrier 3 prevents the processor running B() from relying on cache for the value of _complete forcing a read from the main memory. Note however that stale cache isn't the only thing which can prevent freshness guarantee in the absence of memory barriers 2 and 3. Reordering of operations on the memory bus is another example of such mechanism.

  3. Memory barrier just ensures that the effects of memory access operations are ordered across the barrier. Other instructions (e.g. increment a value in a register) may still be reordered.

like image 98
Adam Zalcman Avatar answered Oct 17 '25 04:10

Adam Zalcman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!