相信大家对单例模式应该不陌生,每个人都能写出好多种单例模式的实现,总结来说就有五种:懒汉、饿汉、静态内部类、枚举和双重检查锁定。针对这几种方式的代码,可以在网上搜索到,这里就不再细说。
最近又看了一遍单例的几种实现方式,发现了一些其他东西。先看以下单例模式的实现代码
public class Singleton2 {
private Singleton2(){}
private static Singleton2 instance;
public static synchronized Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
private Singleton2(){}
private static Singleton2 instance;
public static synchronized Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
这种实现方式利用了同步的方式保证线程安全,但是效率特别低下,同步锁要善用。
为了提高效率,可以把同步锁放到方法里,先判断instance是否为空,若不为空加锁进行初始化,若为空就可以直接获取对象,这样可以减少一大部分的线程等待,代码如下:
public class Singleton7 {
private Singleton7(){}
private Singleton7(){}
private static Singleton7 instance;
public static Singleton7 getInstance() {
if (instance == null) {
synchronized (Singleton7.class) {
if (instance == null) {
instance = new Singleton7();
}
}
}
return instance;
}
}
现在提个问题,以上代码真的正确吗?觉得代码没问题的人,可以继续往下看,能看出问题的,估计下面的东西也知道。
这里先把问题点明,以上代码中这一行private static Singleton7 instance;是有问题的,缺少了修饰符volatile,这个可是很重要的。
这里先说明类初始化大概的流程:
1、分配内存空间
2、初始化对象
3、设置instance指向分配的内存地址
但是在这三步中,第二步和第三步是可以调换顺序的,也即
1、分配内存空间
3、设置instance指向分配的内存地址
2、初始化对象
基于上面的理论,以上代码在缺少volatile的情况下,会有以下问题
从图中大致能看出B线程虽然获取到了instance对象,但这个对象其实没有真正初始化。
知道这个问题之后,volatitle在这里就能起到至关重要的作用了,使用了volatitle之后,在JDK1.5之后,类初始化流程中第二步和第三步在多线程的情况会被禁止,从而保证代码的正常执行。
相关推荐
综上所述,单例模式和双重检查锁定的正确实现需要程序员深入理解多线程编程、Java内存模型以及设计模式。在实践中,应当根据具体需求和环境选择合适的实现策略,并注意相关技术的适用性和潜在问题,以确保代码的健壮...
单例模式的核心在于控制类的实例化过程,常见的实现方式有懒汉式、饿汉式和双重检查锁定(DCL)等。懒汉式是在类被加载时并不创建实例,而是在第一次调用getInstance方法时才创建;饿汉式则是在类加载时就创建实例,...
4. 双重检查锁定(DCL,线程安全): 使用volatile关键字保证线程可见性和避免指令重排序,确保多线程环境下的安全性。 ```csharp public class Singleton { private static volatile Singleton instance; ...
在Java中,可以使用双重检查锁定(Double-Check Locking)来实现线程安全的单例: ```java public class Singleton { private static volatile Singleton instance; private Singleton() {} public static ...
单例模式有多种实现方式,常见的包括懒汉式、饿汉式以及双重检查锁定(DCL)等。 1. 懒汉式:懒汉式是在第一次使用时才创建单例对象,以延迟加载提高效率。但是,如果在多线程环境下,没有正确处理同步问题,可能...
在C++编程中,单例模式是一种...这种实现方式既简单又高效,避免了传统实现(如双重检查锁定)可能存在的性能问题。在实际项目中,根据具体需求,可以进一步扩展单例模式,例如添加懒加载特性或在析构时进行资源清理。
接下来是**双重检查锁定(Double-Check Locking)**,它结合了懒汉式和饿汉式的优点,既延迟初始化,又保证了线程安全。代码如下: ```java public class Singleton { private volatile static Singleton instance...
有一种双重检查锁定(Double-Checked Locking)的优化方式,可以在保证线程安全的同时降低同步开销。 总结来说,工厂设计模式和单例模式都是软件开发中的重要工具,它们有助于提高代码的可读性、可维护性和可扩展性...
在这里,`volatile`关键字保证了`instance`的可见性和禁止指令重排序,而双重检查锁定避免了不必要的同步开销,确保了线程安全且只实例化一次。 在学生管理系统中,我们可以将学生信息、操作记录等数据封装到这个...
单例模式是软件设计模式中的一种基础且广泛应用的模式,它的主要目的是确保一个类只有一个实例...在Java中,推荐使用双重检查锁定的懒汉式或静态内部类的饿汉式,它们在保证线程安全的同时,兼顾了性能和资源利用效率。
本文将详细讨论四种常见的单例实现方式:饿汉模式、懒汉模式、双重检查锁定(DCL)单例模式以及枚举单例。 1. **饿汉模式**: 饿汉模式是在类加载时就完成了实例化,避免了线程同步问题。这种方式简单且安全,但...
3. **双重检查锁定(DCL,Double Check Locking)单例模式**:结合了饿汉模式和懒汉模式的优点,既延迟了初始化,又保证了线程安全。在多线程环境下,只有在`instance`为`null`时才会进入同步块,避免了不必要的同步...
在Java中,懒汉式的单例模式通常通过双重检查锁定(Double-Check Locking,DCL)来实现,这是一种线程安全的方式。下面是一个简单的DCL实现的懒汉式单例模式代码示例: ```java public class Singleton { private ...
4. **双重检查锁定(DCL)单例**: 结合了懒汉式的延迟初始化和饿汉式的线程安全性,更高效。 ```java public class Singleton { private volatile static Singleton instance; private Singleton() {} public...
4. 双重检查锁定(DCL,线程安全): 结合了懒汉式和线程安全性,避免了同步带来的性能开销。 ```java public class Singleton { private volatile static Singleton instance; private Singleton() {} public ...
除了懒汉式和双重检查锁定,还有饿汉式(静态初始化)单例,它在类加载时就完成了实例化,线程安全且效率高,但可能导致不必要的内存占用。 ```cpp class Singleton { private: Singleton() {} static Singleton ...
5. 双重检查锁定(DCL,线程安全): 在`instance`为null且同步创建之前,进行第二次检查,提高效率。 ```java public class Singleton { private volatile static Singleton instance; private Singleton() {}...
3、懒汉式单例(双重检查锁定) public class Singleton3 { private Singleton3() {} private static Singleton3 single = null; public static Singleton3 getInstance() { if (single == null) { ...
在懒汉式的基础上,加入了双重检查锁定(Double-Check Locking),确保线程安全的同时减少同步开销。 ```java class Singleton { private volatile static Singleton instance = null; private Singleton() {}...