In Java programs, it may sometimes be necessary to postpone some high-overhead object initialization operations and are only initialized when using these objects. This is called delayed initialization or lazy loading
Look at an unsafe delay initialization:
After thread A executes 1, it finds that the object instance is null and is ready to new it, while thread B is new first, which causes an error.
We can use synchronization locks to ensure correctness:
But synchronizing the entire method is too expensive, and people came up with double check locking:
The synchronization lock used in the minimum range seems to achieve the purpose using double checking, but this has a problem: when A executes thread 4, thread B's 7 has not yet been executed, and thread A determines instance != null. Thread B's 7 has not yet been executed, so why does this happen?
Take a look at the underlying key implementation of new Instance():
In fact, it is to first perform 1 allocate memory, then initialize the object and set the instance. Then there is a reorder here, and the order of 2 and 3 may be replaced:
So when B still executes 7, A determines at 4 that the instance object has been initialized. If the instance is called before ctorInstance(memory) will cause an error.
There are two solutions:
1. Declare the instance object as volatile, it will prohibit reordering of 2 and 3
2. Using a solution based on class initialization: The JVM will perform class initialization in the initialization stage of the class (that is, after Class is loaded and before it is used by the thread). exist
During the initialization of the execution class, the JVM will acquire a lock. This lock can synchronize the initialization of the same class by multiple threads
We will find that the implementation code of the scheme based on class initialization is simpler. But the dual check locking scheme based on volatile has an additional advantage: in addition to delay initialization of static fields, it can also delay initialization of instance fields. Field delay initialization reduces the overhead of initializing classes or creating instances, but increases the overhead of accessing fields that are delayed initialized. Most of the time, normal initialization is better than delayed initialization. If you really need to use thread-safe late initialization for instance fields, please use the volatile-based delay initialization scheme described above; if you really need to use thread-safe late initialization for static fields, please use the class-based initialization scheme described above.
Summarize
The above is the implementation code of Java double check lock introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!