Object creation (state initialisation) and thread safety

后端 未结 4 1032
你的背包
你的背包 2021-01-24 17:18

I am look into the book \"Java Concurrency in Practice\" and found really hard to believe below quoted statement (But unfortunately it make sense).

http://www.informit.c

相关标签:
4条回答
  • 2021-01-24 17:24

    the comment:

    the Object constructor first writes the default values to all fields before subclass constructors run

    seems wrong. My prior experience is that the default values for a class are set before its constructor is run. that is a super class will see its init-ed variables set before its constructor runs and does things. This was root of bug a friend looked at where a base class was calling a method during construction that the super class implemented and set a reference that was defined with initialization to null in the super class. the item would be there until entry to the constructor at which time the init set it to null value.

    references to the object are not available to another thread (assuming none generated in the constructor) until it completes construction and object reference is returned.

    0 讨论(0)
  • 2021-01-24 17:38

    When creating a new object things happen sequentially. I don't know the precise order, but it's something like: allocate the space and initialize it to zeroes, then set the fields that get constant values, then set the fields that get calculated values, then run the constructor code. And, of course, it's got to initialize the subclasses in there somewhere.

    So if you try to work with an object that is still being constructed, you can see odd, invalid values in the fields. This doesn't usually happen, but ways to do it:

    • Reference a field that doesn't yet have a value during an assignment to another field.

    • Reference a value in the constructor that doesn't get assigned till later in the constructor.

    • Reference a field in an object in a field in an object that was just read from an ObjectInputStream. (OIS often takes a long time to put values in objects it's read.)

    • Before Java 5, something like:

      public volatile MyClass  myObject;
      ...
      myObject = new MyClass( 10 );
      

      could make trouble because another thread could grab the reference to myObject before the MyClass constructor was finished and it would see bad values (zero instead of 10, in this case) inside the object. With Java 5, the JVM is not allowed to make myObject non-null until the constructor is finished.

    • And today you can still set myObject to this within the constructor and accomplish the same thing.

    If you're clever, you can also get hold of Class fields before they've been initialized.

    In your code example, (n != n) would be true if something changed the value between the two reads of n. I guess the point is n starts as zero, get's set to something else by the constructor, and assertSanity is called during the construction. In this case, n is not volatile so I don't think the assert will ever be triggered. Make it volatile and it will happen once every million times or so if you time everything precisely right. In real life this kind of problem happens just often enough to wreak havoc but rarely enough that you can't reproduce it.

    0 讨论(0)
  • 2021-01-24 17:47

    I guess theoretically it is possible. It is similar to double checked locking problem.

    public class Test {
        static Holder holder;
    
        static void test() {
            if (holder == null) {
                holder = new Holder(1);
            }
            holder.assertSanity();
        }
    ...
    

    If test() is called by 2 threads, thread-2 might see the holder in a state when initialization is still in progress so n != n may happen to be true. Here is bytecode for n != n:

    ALOAD 0
    GETFIELD x/Holder.n : I
    ALOAD 0
    GETFIELD x/Holder.n : I
    IF_ICMPEQ L1
    

    as you can see JVM loads field n to operand stack twice. So it may happen that the first var gets value before init and the seccond after init

    0 讨论(0)
  • 2021-01-24 17:48

    You misread the book. It explicitely says:

    The problem here is not the Holder class itself, but that the Holder is not properly published.

    So the above construct if fine. What's not fine is to improperly publish such an object to other threads. The book explains that in details.

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