Do you know why you want to double check the lock volatile field use it?

The origin of the double lock

Single-mode embodiment, the DCL has a (double lock) implementation. In Java programs, and sometimes you may need to postpone some of the high overhead of object initialization operation, and only when these objects start initialization.

Examples of non-coded delay object initialization thread safe below.

Interviewer: Why use double checking locks volatile field?


In UnsafeLazyInitialization class, a thread of execution of code A 1 is assumed at the same time, B 2 thread executes the code. At this point, A thread might see reference to the object instance initialization is not yet complete.

For UnsafeLazyInitialization class, we can implement lazy initialization thread-safe doing synchronized to getInstance () method.

Sample code is as follows.

Interviewer: Why use double checking locks volatile field?


Due to the getInstance () method to do the synchronization process, synchronized will lead to performance overhead. If the getInstance () method is frequently invoked multiple threads, it will lead to a decline in program execution performance.

Conversely, if the getInstance () method will not be invoked frequently by multiple threads, then the delay initialization program will provide satisfactory performance.

Later, he proposed a "smart" Tip: double-checked locking (Double-Checked Locking). I want to reduce synchronization overhead by double-checked locking.

The following example code delay is achieved using double-checked locking initialized.

Interviewer: Why use double checking locks volatile field?


Double-checked locking seems perfect, but this is a wrong optimization!

In the first thread to execute the code read instance is not null, an object reference instance has not been possible to complete the initialization.

Root of the problem

Double check foregoing fourth example of the locked code (instance = new Instance ();) creates an object. This line of code can be divided into three lines of pseudo-code below.

Interviewer: Why use double checking locks volatile field?


Between the upper 3 lines of pseudo code 2 and 3, it may be reordered (in some JIT compiler, this reordering occurs is true), then execution timing of reordering between 2 and 3 as follows:

Interviewer: Why use double checking locks volatile field?


Multi-threaded execution timing table

  • T1 A1: assignment of memory

  • T2 A3: set point memory instance

  • T3 B1: determining whether the instance is empty

  • T4 B2: Since instance is not null, thread B will access the object instance reference

  • T5 A2: initialize the object

  • T6 A4: access to the object instance references

After know the root of the problem happening, we can think of two ways to achieve lazy initialization thread-safe.

1) does not allow 2 and 3 reordering 2) allows the reordering 2 and 3, but does not allow other threads to "see" this reordering.

Both solutions described later, corresponding to the above two points.

A Solution

Based volatile solutions

Interviewer: Why use double checking locks volatile field?


Note: This solution requires version JDK5 or later (since start using the new JSR-133 specification memory model from JDK5, this specification enhances the semantics of volatile).

When an object is declared after a reference volatile, re-ordering between the rows 3 and 2, pseudo-code 3, in a multithreaded environment it will be prohibited.

Solution two

Class-based solutions for initialization

(Ie, before the Class is loaded, and the threads) JVM's class initialization phase, will perform initialization class.

During initialization execution class, JVM will go to get a lock. The lock can synchronize multiple threads to initialize the same class.

Based on this feature, you can achieve another thread-safe lazy initialization program (this program is called Initialization On Demand Holder idiom).

Interviewer: Why use double checking locks volatile field?


Field initialization delay reduces the cost of creating or initializing a class instance, but increases the cost of access is lazy initialization field.

Most of the time, better than normal initialization delay initialization. If you do need a delay to initialize the instance fields using thread-safe, use the description above based on lazy initialization of volatile solution; if you really need a delay to initialize static fields using thread-safe, use the description above class-based initialization scheme.

Little brother feel good essays give a point to focus on it, give it more gradually.

Finally, share an interview book "Java Core knowledge finishing .pdf", covering the JVM, locks, high concurrency, reflection, Spring principle, micro-services, Zookeeper, databases, data structures, and so on. Add to my personal fan base (Java technology stack architecture: 644 872 653) for a free way to receive.


Guess you like

Origin blog.51cto.com/14480698/2458428