JAVA double check locking and deferred initialization

Source: Internet
Author: User
Tags volatile

The origin of the double check lock
In Java programs, it is sometimes necessary to postpone initialization of some high-overhead objects, and to initialize the object only when it is actually used, you need to defer the initialization technique.
The correct implementation of lazy initialization requires some skill, otherwise prone to problems, described below.

Scenario 1

 public  class   unsafelazyinit{ private  static   Instance Instance;  public  static   Instance getinstance () { if  (Instance =  ) {instance  = new   Instance ();   return   instance; } }   

The mistake of this approach is obvious, if two threads call getinstance, because access to shared variables is not synchronized, it is easy to see the following two scenarios:
1. Threads A and B both see that the instance is not initialized, so they are initialized separately.
2.instance=new The instance operation is reordered, the actual execution may be: Allocate memory first, then assign to instance, and then initialize.
If this is the case, other threads may read the instance object that has not yet been initialized.

Scenario 2

 Public class  Privatestatic  Instance Instance;    Public Static synchronized Instance getinstance () {     ifnull) {          new Instance ();      }       return instance;  

The problem with this approach is that it is clear that each read instance needs to be synchronized and may have a significant impact on performance.

Scenario 3

Scenario 3 is a false double detection lock implementation, see Code:

 Public classunsafelazyinit{Private StaticInstance Instance;  Public StaticInstance getinstance () {if(Instance = =NULL) {synchronized (unsafelazyinit.classs) {if(Instance = =NULL) {instance=NewInstance (); }           }      }      returninstance; } } 

This solution seems to solve the problems in both scenarios, but there are also problems.

Source of the problem

New Instance ();

This statement, in practice, may be split into three statements, as follows:

Memory =/ ///

According to the reordering rules, the latter two statements do not have data dependencies, so they can be reordered.
After reordering, it means that after the instance domain is assigned, the object pointed to may not have been initialized, and the instance domain is a static domain.
Can be read by other threads, then other threads can read to the instance domain that has not yet been initialized.

Volatile-based solutions

To solve this, you only need to suppress the reordering of statements 2 and 3, so you can use volatile to modify the instance.

Private volatile Static Instance Instance;

Because volatile semantics prevents the compiler from reordering operations that precede volatile writes to volatile.

Class-Based initialization solutions

The Java language Specification specifies that for each class or interface C, there is a unique initialization lock LC corresponding to it, from C to LC mapping, implemented by the JVM.
When each thread reads information from a class, if the class has not yet been initialized, it attempts to get the LC to initialize and waits for other threads to release the LC if the acquisition fails.
If the LC can be obtained, the initialization state of the class is determined, and if it is bit-initialized, it is initialized. If it is initializing,
Wait for other thread initialization to complete, and if it is already initialized, use such an object directly.

 Public class instancefactory{     privatestaticclass  instanceholder{            publicstaticnew  Instance ();      }             Public Static Instance getinstance () {         return//    }     

Conclusion

Field lazy initialization reduces the overhead of initializing a class or creating an instance, but increases the cost of a field that is delayed by 0 access.
Most of the time, normal initialization is better than lazy initialization. If you do need to use thread-safe deferred Initialization for instance fields,
Use the volatile-based deferred initialization scheme described above, and if you do need to use thread-safe deferred initialization for static fields,
Use the above deferred initialization based on the class initialization scheme.

JAVA double check locking and deferred initialization

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.