Using atomic links in an example of an effective jave effect

In Effective Java - Paragraph 74 Joshua Bloch demonstrates the safe use of a parameterless constructor using a separate initialization method in the following code fragment.

abstract class AbstractFoo {
            private int x, y; // Our state
                    // This enum and field are used to track initialization

            private enum State {
                NEW, INITIALIZING, INITIALIZED
            };

            private final AtomicReference<State> init = new AtomicReference<State>(
                    State.NEW);

            public AbstractFoo(int x, int y) {
                initialize(x, y);
            }

            // This constructor and the following method allow
            // subclass readObject method to initialize our state.
            protected AbstractFoo() {
            }

            protected final void initialize(int x, int y) {
                if (!init.compareAndSet(State.NEW, State.INITIALIZING))
                    throw new IllegalStateException("Already initialized");
                this.x = x;
                this.y = y;
                // ...Do anything else the original constructor did
                init.set(State.INITIALIZED);
            }

            // These methods provide access to internal state so it can
            // be manually serialized by subclass writeObject method.
            protected final int getX() {
                checkInit();
                return x;
            }

            protected final int getY() {
                checkInit();
                return y;
            }

            // Must call from all public and protected instance methods
            private void checkInit() {
                if (init.get() != State.INITIALIZED)
                    throw new IllegalStateException("Uninitialized");
            }

        }

I am puzzled by the use AtomicReference. His explanation is:

Note that the initialized field is an atom reference (Java.util.concurrent.atomic.AtomicReference). This is necessary to ensure the integrity of the object in the face of a specific enemy. in the absence of this precaution, if one thread was to initiate an initialization of the instance while the second thread tried to use it, the second thread might see the instance in an inconsistent state.

, . , initialize(), , , x y , .

, , , AtomicReference (, ). init , IllegalStateException, , , , . , ?

? ?

+4
3

, , - , , , .

, , /JVM . , A :

field1 = "hello";
field2 = "world";

B:

System.out.println(field2);
System.out.println(field1);

, B "", "null" (, field1). , field2 field1 — , field2 , , , field1 ? ! , 2 :

field2 = "world";
field1 = "hello";

( field2 = "world" field1 = "hello", , .) , : - , , , . , .

...

, - ( , final ). -, , -, , -, . , , ( , , ?), - . , foo = new ConcreteFoo():

  • ConcreteFoo ( this); initalize, -...
  • this.x = x
  • this.y = y
  • foo = <the newly constructed object>

, ; B , ( ):

  • foo = <the newly constructed object, with default values for all fields>
  • foo.getX(), 0
  • this.x = x ( )
  • (this.y = y B)

,

. AtomicReference ...

(HB). HB, CPU .

:

  • A A
  • B - B
  • A B
  • , B B, , , , A A. , B "" A saw .

, . , , - volatile: HB , , , . , A volatile, B , B A, (, , : B ).

, field2 volatile. :

Thread 1:
field1 = "hello";
field2 = "world"; // point 1

Thread 2:
System.out.println(field2); // point 2
System.out.println(field1); // point 3

1 "" HB, 2 ". , 2 2 , 1 1 — , field1 = "hello" ( field2 = "world"). , 2 " world \n hello", .

AtomicReferences

, AtomicReference? javadoc java.util.concurrent.atomic:

, 17.4 Java ™.

, HB myAtomicRef.set myAtomicRef.get. , , myAtomicRef.compareAndSet myAtomicRef.get.

AbstractFoo

AtomicReference AbstractFoo HB. this.x ( initialize, ), this.x ( getX), , getX x ( 0).

AbstractFoo HB: initialize init.set this.x = x, getX init.get ( checkInit), this.x > , ( y). HB, , 2, getX, , this.x, A, initialize, init.set; , 2 this.x = x, return [this.]x.

- , . JLS 17.4.4.

JCIP, Java .

+6

, AtomicReference-before , , init.set(State.INITIALIZED);, , , init.get(). , compareAndSet , . : java , synchronized.

0

, non-arg "initialize" (, getX()) . AtomicReference , checkInit , , , "" . AtomicReference "", .

, , , , "" , , , AtomicReference .

-1
source

Source: https://habr.com/ru/post/1531441/


All Articles