What are memory fences used for in Java?

后端 未结 1 613
长发绾君心
长发绾君心 2020-12-31 02:20

Whilst trying to understand how SubmissionPublisher (source code in Java SE 10, OpenJDK | docs), a new class added to the Java SE in version 9, has been impleme

相关标签:
1条回答
  • 2020-12-31 03:13

    This is mainly a non-answer, really (initially wanted to make it a comment, but as you can see, it's far too long). It's just that I questioned this myself a lot, did a lot of reading and research and at this point in time I can safely say: this is complicated. I even wrote multiple tests with jcstress to figure out how really they work (while looking at the assembly code generated) and while some of them somehow made sense, the subject in general is by no means easy.

    The very first thing you need to understand:

    The Java Language Specification (JLS) does not mention barriers, anywhere. This, for java, would be an implementation detail: it really acts in terms of happens before semantics. To be able to proper specify these according to the JMM (Java Memory Model), the JMM would have to change quite a lot.

    This is work in progress.

    Second, if you really want to scratch the surface here, this is the very first thing to watch. The talk is incredible. My favorite part is when Herb Sutter raises his 5 fingers and says, "This is how many people can really and correctly work with these." That should give you a hint of the complexity involved. Nevertheless, there are some trivial examples that are easy to grasp (like a counter updated by multiple threads that does not care about other memory guarantees, but only cares that it is itself incremented correctly).

    Another example is when (in java) you want a volatile flag to control threads to stop/start. You know, the classical:

    volatile boolean stop = false; // on thread writes, one thread reads this    
    

    If you work with java, you would know that without volatile this code is broken (you can read why double check locking is broken without it for example). But do you also know that for some people that write high performance code this is too much? volatile read/write also guarantees sequential consistency - that has some strong guarantees and some people want a weaker version of this.

    A thread safe flag, but not volatile? Yes, exactly: VarHandle::set/getOpaque.

    And you would question why someone might need that for example? Not everyone is interested with all the changes that are piggy-backed by a volatile.

    Let's see how we will achieve this in java. First of all, such exotic things already existed in the API: AtomicInteger::lazySet. This is unspecified in the Java Memory Model and has no clear definition; still people used it (LMAX, afaik or this for more reading). IMHO, AtomicInteger::lazySet is VarHandle::releaseFence (or VarHandle::storeStoreFence).


    Let's try to answer why someone needs these?

    JMM has basically two ways to access a field: plain and volatile (which guarantees sequential consistency). All these methods that you mention are there to bring something in-between these two - release/acquire semantics; there are cases, I guess, where people actually need this.

    An even more relaxation from release/acquire would be opaque, which I am still trying to fully understand.


    Thus bottom line (your understanding is fairly correct, btw): if you plan to use this in java - they have no specification at the moment, do it on you own risk. If you do want to understand them, their C++ equivalent modes are the place to start.

    0 讨论(0)
提交回复
热议问题