7 ways to create, take you to understand Java's singleton mode

This article is shared from Huawei Cloud Community " Java Minimalist Design Patterns" Chapter 01: Singleton Mode (Singleton) ", author: Binghe.

singleton design pattern

Look at several sample codes of singleton objects, some of which are thread-safe, and some are not. You need to savor them carefully. These codes have also been tested and verified in a high-concurrency environment.

  • Code 1: SingletonExample1

This class is lazy mode and is not thread safe

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Lazy mode, the singleton instance is created when it is used for the first time, this class is not thread-safe

*/

public class SingletonExample1 {

private SingletonExample1(){}

private static SingletonExample1 instance = null;

public static SingletonExample1 getInstance(){

//Multiple threads call at the same time, may create multiple objects

if (instance == null){

instance = new SingletonExample1();

}

return instance;

}

}
  • Code 2: SingletonExample2

Hungry man mode, singleton instance is created when the class is loaded, which is thread-safe

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Hungry man mode, the singleton instance is created when the class is loaded, which is thread-safe

*/

public class SingletonExample2 {

private SingletonExample2(){}

private static SingletonExample2 instance = new SingletonExample2();

public static SingletonExample2 getInstance(){

return instance;

}

}
  • Code 3: SingletonExample3

Lazy mode, the singleton instance is created when it is used for the first time, this class is thread-safe, but this way of writing is not recommended

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Lazy mode, the singleton instance is created when it is used for the first time, this class is thread-safe, but this way of writing is not recommended

*/

public class SingletonExample3 {

private SingletonExample3(){}

private static SingletonExample3 instance = null;

public static synchronized SingletonExample3 getInstance(){

if (instance == null){

instance = new SingletonExample3();

}

return instance;

}

}
  • Code 4: SingletonExample4

Lazy mode (double lock synchronous lock singleton mode), the singleton instance is created when it is used for the first time, but this class is not thread-safe! ! ! ! !

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Lazy mode (double lock synchronous lock singleton mode)

* The singleton instance is created when it is used for the first time, this class is not thread-safe

*/

public class SingletonExample4 {

private SingletonExample4(){}

private static SingletonExample4 instance = null;

//Thread unsafe

//When the instance = new SingletonExample4(); line of code is executed, the CPU will execute the following instructions:

//1.memory = allocate() allocates the memory space of the object

//2.ctorInstance() initializes the object

//3.instance = memory Set instance to point to the memory just allocated

//There is nothing wrong with simply executing the above three steps, but in the case of multi-threading, instruction reordering may occur.

// Instruction reordering has no effect on single thread. Under single thread, the CPU can execute the above three steps in order. However, under multithreading, if instruction reordering occurs, the above three steps will be disrupted.

//If JVM and CPU optimization occurs, when reordering occurs, it may be executed in the following order:

//1.memory = allocate() allocates the memory space of the object

//3.instance = memory Set instance to point to the memory just allocated

//2.ctorInstance() initializes the object

//Suppose there are currently two threads A and B executing the getInstance() method at the same time, A thread executes to instance = new SingletonExample4(); B thread just executes to the first if (instance == null){,

//If you follow the order of 1.3.2, assuming that thread A executes to 3.instance = memory and sets instance to point to the memory just allocated, at this time, thread B judges that instance has a value, and returns instance directly;

//In fact, thread A has not yet executed 2. ctorInstance() to initialize the object, that is to say, the instance object obtained by thread B has not yet been initialized. Once this uninitialized instance object is used by thread B, problems will occur .

public static SingletonExample4 getInstance(){

if (instance == null){

synchronized (SingletonExample4.class){

if(instance == null){

instance = new SingletonExample4();

}

}

}

return instance;

}

}

Thread unsafe analysis is as follows:

When executing the instance = new SingletonExample4(); line of code, the CPU will execute the following instructions:

1.memory = allocate() allocates the memory space of the object

2. ctorInstance() initializes the object

3.instance = memory Set instance to point to the memory just allocated

There is nothing wrong with simply executing the above three steps, but in the case of multi-threading, instruction reordering may occur.

Instruction reordering has no effect on a single thread. Under a single thread, the CPU can execute the above three steps in order. However, under multithreading, if instruction reordering occurs, the above three steps will be disrupted.

If JVM and CPU optimizations occur, when reordering occurs, it may be executed in the following order:

1.memory = allocate() allocates the memory space of the object

3.instance = memory Set instance to point to the memory just allocated

2. ctorInstance() initializes the object

Suppose there are currently two threads A and B executing the getInstance() method at the same time, A thread executes to instance = new SingletonExample4(); B thread just executes to the first if (instance == null){, if according to 1.3.2 Assume that thread A executes to 3.instance = memory and sets instance to point to the memory just allocated. At this time, thread B judges that instance has a value, and returns instance directly; in fact, thread A has not yet executed 2.ctorInstance () Initialize the object, that is to say, the instance object obtained by thread B has not been initialized. Once this uninitialized instance object is used by thread B, problems will occur.

  • Code five: SingletonExample5

Lazy mode (double lock synchronous lock singleton mode) singleton instance is created when it is used for the first time. This class is thread-safe, using volatile + double detection mechanism to prohibit instruction rearrangement to achieve thread safety

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Lazy mode (double lock synchronous lock singleton mode)

* The singleton instance is created when it is used for the first time, this class is thread-safe

*/

public class SingletonExample5 {

private SingletonExample5(){}

//Singleton object volatile + double detection mechanism to prohibit instruction rearrangement

private volatile static SingletonExample5 instance = null;

public static SingletonExample5 getInstance(){

if (instance == null){

synchronized (SingletonExample5.class){

if(instance == null){

instance = new SingletonExample5();

}

}

}

return instance;

}

}
  • Code six: SingletonExample6

Hungry man mode, singleton instance is created when the class is loaded (using static code block), which is thread-safe

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description Hungry man mode, the singleton instance is created when the class is loaded, which is thread-safe

*/

public class SingletonExample6 {

private SingletonExample6(){}

private static SingletonExample6 instance = null;

static {

instance = new SingletonExample6();

}

public static SingletonExample6 getInstance(){

return instance;

}

}
  • Code Seven: SingletonExample7

The enumeration method is instantiated, which is thread-safe, and this method is also the most thread-safe

package io.binghe.concurrency.example.singleton;

/**

* @author binghe

* @version 1.0.0

* @description The enumeration method is instantiated, which is thread-safe, and this method is also the most thread-safe

*/

public class SingletonExample7 {

private SingletonExample7(){}

public static SingletonExample7 getInstance(){

return Singleton.INSTANCE.getInstance();

}

private enum Singleton{

INSTANCE;

private SingletonExample7 singleton;

//JVM guarantees that this method is called only once

Singleton(){

singleton = new SingletonExample7();

}

public SingletonExample7 getInstance(){

return singleton;

}

}

}

Click to follow and learn about Huawei Cloud's fresh technologies for the first time~

The Indian Ministry of Defense self-developed Maya OS, fully replacing Windows Redis 7.2.0, and the most far-reaching version 7-Zip official website was identified as a malicious website by Baidu. Go 2 will never bring destructive changes to Go 1. Xiaomi released CyberDog 2, More than 80% open source rate ChatGPT daily cost of about 700,000 US dollars, OpenAI may be on the verge of bankruptcy Meditation software will be listed, founded by "China's first Linux person" Apache Doris 2.0.0 version officially released: blind test performance 10 times improved, More unified and diverse extremely fast analysis experience The first version of the Linux kernel (v0.01) open source code interpretation Chrome 116 is officially released
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4526289/blog/10098446