Search code examples
javac++cx86memory-barriers

Is memory barrier necessary for memory consistency?


After reading Memory Barriers: a Hardware View for Software Hackers, I came up with a point which I am not sure of its correctness, as posted in the title. I came up with this point because of intuition from the CPU cache level (which I am not sure of either): as the MESI protocol and its families guarantee coherence, memory consistency requires memory fences to synchronize across multiple processors, and this requirement would reflect into the programming language internals.

I tried to validate the point with my limited experience:

  1. For C++, fences are directly referred to in its atomic methods, while both of them are applicable for delivering memory consistency;
  2. For Java, Atomic and Lock(AQS) use volatile internally, which employs a memory fence as well.

So I wonder whether memory fence is the ultimate answer to these synchronization issues.

If the point in the title is too strong, I would wonder whether this point holds in any specific processor, such as x86, ARM, etc.

I really appreciate any advice and keywords.


Solution

  • So I wonder whether memory fence is the ultimate answer to these synchronization issues.

    In the Java case, this is the wrong approach. While it may be true for past and current HotSpot JVM implementations ... it is (at best) an implementation detail. It may not be true for future implementations and/or hardware platforms.

    In Java, the correct way to understand these things is in terms of the Java Memory Model (JLS Chapter 17.4). The JMM spec does not talk about caches, memory barriers or registers. Rather, it talks in terms of happens before relations. If your code can be shown to have a happens before chain from a write to a shared variable and subsequent read of that variable, then certain memory visibility properties are guaranteed.

    Under the hood, the memory visibility guarantees are (typically) implemented using memory barriers (of different kinds, depending on the GC) and by influencing the JIT compiler's register usage. But the Java programmer doesn't need to know that.