Double check locking and delay initialization in Java programs

Source: Internet
Author: User
Tags execution thread java se

In Java programs, it is sometimes possible to postpone some expensive object initialization operations and initialize them only when they are used. At this point, the programmer may adopt deferred initialization. However, there are some techniques to properly implement thread-safe delay initialization, otherwise it is easy to have problems. For example, the following is a sample code for a lazy initialization object that is not thread-safe:

public class Unsafelazyinitialization {
private static Instance Instance;
public static Instance getinstance () {
if (Instance = null)//1:a thread execution
Instance = new Instance ();//2:b Thread Execution
re Turn instance
}
}

In Unsafelazyinitialization, if a thread executes code 1, the B thread executes code 2. At this point, thread A may see that the object referenced by instance has not completed initialization (see the cause of the problem in the following article).

For unsafelazyinitialization, we can do synchronous processing of getinstance () to implement thread-safe delay initialization. The sample code is as follows:

public class Safelazyinitialization {
    private static Instance Instance;

    Public synchronized static Instance getinstance () {
        if (Instance = = null)
            Instance = new Instance ();
        return instance
    }
}

Because the getinstance () has been synchronized, synchronized will incur performance overhead. If getinstance () is called frequently by multiple threads, it will cause performance degradation of the program execution. Conversely, if getinstance () is not frequently invoked by multiple threads, this delayed initialization scheme will provide satisfactory performance.

In the early JVM, synchronized (even the synchronized) had this huge performance overhead. So people come up with a "smart" trick: Double check Locking (double-checked locking). People want to reduce the overhead of synchronization by double check locking. The following is a sample code that uses a double check lock to implement deferred initialization:

public class Doublecheckedlocking {                 //1
    private static Instance Instance;                    2 public

    static Instance getinstance () {               //3
        if (Instance = = null) {                          //4: Check synchronized for the first time
            ( Doublecheckedlocking.class) {  //5: Lock
                if (instance = null)                    //6: Second check
                    instance = new instance ();           7: The root of the problem is here
            }                                            //8
        }//9 return
        instance;                                 Ten
    }                                                    //11
}                                                        //12

As the code above shows, if the first check instance is not NULL, then you do not need to perform the following lock and initialization operations. This can significantly reduce the performance overhead associated with synchronized. The code above looks like the most of the worlds:

When multiple threads attempt to create an object at the same time, a lock is added to ensure that only one line Cheng Nen the object.

After the object is created, executing getinstance () does not need to acquire the lock and returns the created object directly.

Double check locking looks perfect, but it's a mistake to optimize! When a thread executes to the 4th line of code reading to instance is not NULL, the object referenced by instance may not have completed initialization.

The root of the problem

The previous double check locks the 7th line of the sample code (instance = new Singleton ();) to create an object. This line of code can be broken down into the following three lines of pseudo code:

Memory = allocate ();   1: Allocating the object's memory space
ctorinstance (memory);  2: Initialization Object
instance = memory;     3: Set instance point to the memory address just allocated

Between 2 and 3 of the above three lines of pseudocode, it may be reordered (on some JIT compilers, this reordering is true, as detailed in the "Out-of-order writes" section of reference 1). The execution sequence after reordering between 2 and 3 is as follows:

Memory = allocate ();   1: Allocating the object's memory space
instance = memory;     3: Set the instance point to the memory address just allocated
                       /Note that the object has not been initialized at this time!
ctorinstance (memory);  2: Initializing the object

According to the Java Language specification, Java SE 7 Edition (hereafter referred to as the Java Language Specification), all threads must comply with the Intra-thread semantics when executing Java programs. Intra-thread semantics guaranteed reordering does not change the results of program execution within a single thread. In other words, intra-thread semantics allows reordering of the results of single-threaded routines that do not alter the execution of a single threaded process. The above three lines of pseudo code between 2 and 3 are reordered, but this reordering does not violate intra-thread semantics. This reordering can improve the execution performance of the program without changing the execution result of the single-threaded process.

For a better understanding of intra-thread semantics, see the diagram below (assuming that a thread a accesses the object immediately after the object is constructed):

As shown in the figure above, it does not violate intra-thread semantics, as long as you ensure that 2 rows are in front of 4, even if you reorder between 2 and 3.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.