Effectively Immutable Object

后端 未结 3 1891
眼角桃花
眼角桃花 2021-01-31 22:09

I want to make sure that I correctly understand the \'Effectively Immutable Objects\' behavior according to Java Memory Model.

Let\'s say we have a mutable class which

3条回答
  •  没有蜡笔的小新
    2021-01-31 22:49

    There is a couple of conditions which must be met for the Java Memory Model to guarantee that Outworld.published.get() == 3:

    • the snippet of code you posted which creates and increments the MutableLong, then sets the Outworld.published field, must happen with visibility between the steps. One way to achieve this trivially is to have all that code running in a single thread - guaranteeing "as-if-serial semantics". I assume that's what you intended, but thought it worth pointing out.
    • reads of Outworld.published must have happens-after semantics from the assignment. An example of this could be having the same thread execute Outworld.published = val; then launch other the threads which could read the value. This would guarantee "as if serial" semantics, preventing re-ordering of the reads before the assignment.

    If you are able to provide those guarantees, then the JMM will guarantee all threads see Outworld.published.get() == 3.


    However, if you're interested in general program design advice in this area, read on.

    For the guarantee that no other threads ever see a different value for Outworld.published.get(), you (the developer) have to guarantee that your program does not modify the value in any way. Either by subsequently executing Outworld.published = differentVal; or Outworld.published.increment();. While that is possible to guarantee, it can be so much easier if you design your code to avoid both the mutable object, and using a static non-final field as a global point of access for multiple threads:

    • instead of publishing MutableLong, copy the relevant values into a new instance of a different class, whose state cannot be modified. E.g.: introduce the class ImmutableLong, which assigns value to a final field on construction, and doesn't have an increment() method.
    • instead of multiple threads accessing a static non-final field, pass the object as a parameter to your Callable/Runnable implementations. This will prevent the possibility of one rogue thread from reassigning the value and interfering with the others, and is easier to reason about than static field reassignment. (Admittedly, if you're dealing with legacy code, this is easier said than done).

提交回复
热议问题