简体   繁体   中英

Is object initialization atomic in Java?

I know myObject1 = myObject2 is atomic, but is following line of code atomic?

Object obj1 = new Object();

Can it actually be suspended in the middle of initializing a reference?

It is not atomic. There's nothing stopping you from putting a sleep inside the Object constructor, or an infinite loop, or throwing an exception inside the constructor.

NOTE: Although possible, these are all anti-patterns and are not recommended.

This line is not atomic. Two things happen: first, new Object is created (which is in general is not atomic), and then the reference to this object is assigned to the variable obj1 . Say, the line executed by Thread1 , and Thread2 observes the state of the variable at a random moment. There are three states Thread2 can observe (for simplicity assume object creation itself is atomic),

  1. obj1 == null , the object is not created
  2. obj1 == null , the object is created, but the reference to it is yet to be assigned to the variable
  3. obj1 != null , the line is fully executed

Atomicity would suggest that Thread2 may observe only state 1 and 3, but it has to be enforced. One way to make it atomic is via synchronization (in this example obj1 is a class field):

public synchronized Object getObj() {
    if (obj1 == null)
        obj1 = new Object();

    return obj1;
}

First thread calling this method will initialize the field, and further calls will simply return the variable. Due to mutual exclusion, it is not possible for a thread to observe null in obj1 after the object is created, since method calls by different threads cannot overlap.

The reference assignment is atomic. There is no condition under which the reference itself will be partly assigned (this would obviously cause the VM to crash at times). It will either be null or not-null. The construction of the object before the reference is assigned isn't atomic, but you won't get access to the new object to assign to the reference until the construction process is finished.

Interestingly, the reference assignment can occur in cached memory on the chip that isn't synchronized with main memory. This means other threads won't see the assignment right away. There are two ways to ensure that the reference assignment is pushed through to main memory where other threads can immediately see it. (1) declare the reference as volatile and (2) put the reference assignment in a synchronized block (exiting the synchronized block will commit the cached reference to main memory)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM