Partial constructed objects in the Java Memory Model

这一生的挚爱 提交于 2019-12-04 14:47:45

That article is saying that if you have code like

foo = new MyInt(7);

in a class that has a field

MyInt foo;

then the instructions that amount to

(reference to new object).x = 7;
foo = (reference to new object);

could be swapped over as some kind of optimisation. This will never change the behaviour of the thread that's running this code, but it's possible that some other thread will be able to read foo after the line

foo = (reference to new object);

but before the line

(reference to new object).x = 7;

in which case it would see foo.x as 0, not 7. That is to say, that other thread could run

int bar = someObject.getFoo().getValue();

and end up with bar equal to 0.

I've never seen anything like this happen in the wild, but the author seems to know what he's talking about.

Instruction reordering alone can not lead to another thread seeing a partially constructed object. By definition, the JVM is only allowed to reorder things if they don't affect a correctly synchronized program's behaviour.

It's unsafe publishing of the object reference that enables bad things to happen. Here's a particularly poor attempt at a singleton for example:

public class BadSingleton {
   public static BadSingleton theInstance;

   private int foo;

   public BadSingleton() {
      this.foo = 42;
      if (theInstance == null) {
         theInstance = this;
      }
   }
}

Here you accidentally publish the reference to the object being constructed in a static field. This would not necessarily be a problem until the JVM decides to reorder things and places this.foo = 42 after the assignment to theInstance. So the two things together conspire to break your invariants and allow another thread to see a BadSingleton.theInstance with its foo field uninitialised.

Another frequent source of accidental publication is calling overrideable methods from the constructor. This does not always lead to accidental publication, but the potential is there, hence it should be avoided.

only the thread that creates an object should have access to it while it is being constructed

And does that mean that the statement from the Java Tutorials is simply not true?

Yes and no. It depends on how we interpret the word should. There is no guarantee that in every possible case another thread won't see a partially constructed object. But it's true in the sense that you should write code that doesn't allow it to happen.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!