演示单例类双重检查锁定的Java程序
初级开发人员面临的主要挑战之一是如何将 Singleton 类保持为 Singleton,即如何防止 Singleton 类的多个实例。 Singleton 的双重检查锁定是一种确保在应用程序生命周期中仅创建 Singleton 类实例的一种方法。在双重检查锁定中,代码在锁定和不锁定的情况下两次检查 Singleton 类的现有实例,以确保只创建一个单例实例。
单例类的双重检查锁定的需要:
Java
private static Singleton instance;
public static Singleton getInstance1()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
Java
public static Singleton getInstance2()
{ // Single Checked
if (instance == null) {
synchronized (Singleton.class)
{
// Double checked
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
Java
// Java Program to write double checked locking
// of Singleton class
class Singleton {
private volatile static Singleton instance;
private Singleton() {}
// 1st version: creates multiple instances if two thread
// access this method simultaneously
public static Singleton getInstance1()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 2nd version : this is thread-safe and only
// creates one instance of Singleton on concurrent
// environment but it is unnecessarily expensive due to
// cost of synchronization at every call.
public static synchronized Singleton getInstance2()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 3rd version : An implementation of double checked
// locking of Singleton. Intention is to reduce cost
// of synchronization and improve performance, by only
// locking critical section of code, the code which
// creates instance of Singleton class.
public static Singleton getInstance3()
{
if (instance == null) {
synchronized (Singleton.class)
{
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
- 如果由多个线程并行调用(称为多线程),上述代码将创建 Singleton 类的多个实例。
- 当前问题的主要解决方案是使getInstance() 方法同步。
- 虽然它是线程安全的,解决了多实例的问题,但效率不高。每次调用这个方法都需要承担同步的代价,而同步只需要在第一类,当创建 Singleton 实例时。
这给我们带来了双重检查锁定模式,其中只有代码的关键部分被锁定。
为什么称为双重检查锁定?
- 它被称为双重检查锁定,因为有两个检查,例如 == null,一个没有锁定,另一个有锁定(在同步块内)。
双重检查锁定在Java中的样子:
Java
public static Singleton getInstance2()
{ // Single Checked
if (instance == null) {
synchronized (Singleton.class)
{
// Double checked
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
在 Singleton 类上实现双重检查锁定:
Java
// Java Program to write double checked locking
// of Singleton class
class Singleton {
private volatile static Singleton instance;
private Singleton() {}
// 1st version: creates multiple instances if two thread
// access this method simultaneously
public static Singleton getInstance1()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 2nd version : this is thread-safe and only
// creates one instance of Singleton on concurrent
// environment but it is unnecessarily expensive due to
// cost of synchronization at every call.
public static synchronized Singleton getInstance2()
{
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 3rd version : An implementation of double checked
// locking of Singleton. Intention is to reduce cost
// of synchronization and improve performance, by only
// locking critical section of code, the code which
// creates instance of Singleton class.
public static Singleton getInstance3()
{
if (instance == null) {
synchronized (Singleton.class)
{
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}