最近在一个项目当中遇到了需要一个单实例模型的问题,就认真查了下资料,复习了下java的单例设计
1.饿汉式:在系统启动的时候就讲对象 实例化。
public class Test{
private static Test instance=new Test();
private Test(){}//必须定义为私有的构造方法 使得不能再外部new一个实例
public static Test getInstance(){
return instance;
}
}
2.懒式:在第一次使用到的时候去判断是否为空,然后去实例化
public class Test{
private static Test instance=null;
private Test(){}//必须定义为私有的构造方法 使得不能再外部new一个实例
public static Test getInstance(){
if(instance==null){
instance=new Test();
}
return instance;
}
}
但是 第二种方法只适用于单线程的程序代码当中,不能保证在多线程访问的服务器端程序中运行时候保证单实例。所以在网上出现了将 第二种方法改造为同步锁定的代码如下:
public static synchronized Test getInstance(){
if(instance==null){
instance=new Test();
}
return instance;
}
但于此同时也产生了为了保持同步,必须付出昂贵的代价。事实上只有在第一次使用的时候才用到同步,但是如果把同步加到方法上,就在每一次调用获取实例化对象的时候都将产生同步,这样是在服务器端非常耗资源的。
一些聪明的程序员为了解决这个问题,发明了一个新的名词:“双重检查锁定”,代码如下
public class Test{
private static Test instance=null;
private Test(){}//必须定义为私有的构造方法 使得不能再外部new一个实例
public static Test getInstance(){
if(instance==null){
synchronized (Test .class){
if(instance==null){
instance=new Test();
}
}
}
return instance;
}
}
双重检查锁定背后的理论是完美的。不幸地是,现实完全不同。双重检查锁定的问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。双重检查锁定失败的问题并不归咎于 JVM 中的实现 bug,而是归咎于 Java 平台内存模型。内存模型允许所谓的“无序写入”,这也是这些习语失败的一个主要原因。
多线程访问的时候会 返回一个非null但是没有被实例化的残缺对象
为避免单例中代价高昂的同步,程序员非常聪明地发明了双重检查锁定习语。不幸的是,鉴于当前的内存模型的原因,该习语尚未得到广泛使用,就明显成为了一种不安全的编程结构。重定义脆弱的内存模型这一领域的工作正在进行中。尽管如此,即使是在新提议的内存模型中,双重检查锁定也是无效的。对此问题最佳的解决方案是接受同步或者使用一个 static field
本文来自IBM一位开发工程师的日志 详情请参阅:http://www.ibm.com/developerworks/java/library/j-dcl.html 以及 http://ajava.org/course/java/13502.html
分享到:
相关推荐
- **缺点**:第一次加载时反应不快,由于Java内存模型的一些原因偶尔失败。 - **特点**:结合了饿汉式和懒汉式的优点,既实现了延迟加载,又避免了多线程的同步问题,是一种比较推荐的方式。 #### 四、什么情况下...
### JAVA单例模式的几种实现方法 #### 一、饿汉式单例类 饿汉式单例类是在类初始化时就已经完成了实例化的操作。这种实现方式简单且线程安全,因为实例化过程是在编译期间完成的,不会受到多线程的影响。 **代码...
Java单例设计模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java编程中,单例模式常用于管理共享资源,如数据库连接池、线程池或者配置信息等,以提高效率并减少系统内存开销。这个...
在实际应用中,Java中还有一种双重检查锁定(Double-Checked Locking,DCL)的懒汉式单例实现,它既实现了懒加载,又解决了线程安全问题,但实现起来较为复杂,需要理解Java内存模型和volatile关键字的作用。...
Java 内存模型(Java Memory Model,简称 JMM)是 Java 平台中关于线程如何访问共享变量的一套规则,它定义了线程之间的内存可见性、数据一致性以及指令重排序等关键概念,对于多线程编程和并发性能优化至关重要。...
"Java双重检查加锁单例模式的详解" Java双重检查加锁单例模式是一种常用的单例模式实现方法,但是在多线程环境下,它存在一些问题。在这篇文章中,我们将探讨Java双重检查加锁单例模式的详解,包括它的优点和缺点,...
例如,双重检查锁定问题就是由于旧JMM中的内存模型缺陷所引起的,它可能导致单例模式的实现出现线程安全问题。 JSR 133(Java Memory Model and Thread Specification Revision)正是为了解决这些问题而提出的,它...
Java线程-Java内存模型是Java并发编程中的关键概念,它描述了多个线程如何共享和访问内存资源,以及如何保证数据的一致性和安全性。Java内存模型(JMM)是Java虚拟机规范的一部分,用于定义程序中各个线程对共享变量...
在Java编程语言中,模型设计是一项关键技能,它涉及到如何有效地组织和结构化代码,以实现高效、可维护和可扩展的应用程序。本教程聚焦于Java模型设计,提供了丰富的代码示例,帮助开发者深入理解这一主题。以下是...
Java作为一款广泛应用的面向对象的编程语言,其设计模式的应用对于编写可维护、可扩展和高效的代码至关重要。本篇将深入探讨标题中提及的几种设计模式:Model-View-Controller(MVC)模式、单例模式、代理模式以及...
在Java中,实现单例模式有多种方式,这里提到的是懒汉式单例,它的特点是延迟初始化,即只有当对象被首次使用时才会创建。 懒汉式的单例代码如下: ```java public class Singleton { private static Singleton ...
以下是使用双重检查锁定实现的Java单例模式代码示例: ```java public class Singleton { private volatile static Singleton instance; // 使用volatile关键字保证可见性和有序性 private Singleton() {} // ...
在努力创建更有效的代码时,Java 程序员们创建了双重检查锁定习语,将其和单例创建模式一起使用,从而限制同步代码量。然而,由于一些不太常见的 Java 内存模型细节的原因,并不能保证这个双重检查锁定习语有效。 ...
Java内存模型(JVM Memory Model,简称JMM)是Java平台中的一个重要概念,它定义了在多线程环境下,如何在共享内存中读写变量的行为。JMM的主要目标是确保多线程环境下的可见性、有序性和原子性,从而避免数据不一致...
- 这是一种在多线程环境中创建单例的方法,但在Java中,由于JVM的内存模型问题,简单的双重检查锁定并不总是有效。通常推荐使用`volatile`关键字或`synchronized`块来确保线程安全的单例创建。 5. **单例模式的...
**ISM解释结构模型算法的JAVA实现** ISM,全称为Interpretive Structural Modeling(解释结构建模),是一种系统分析方法,用于理解和描绘复杂系统的相互关系。它由美国学者Warfield在1970年代提出,主要应用于组织...
在Java中,单例模式的实现通常涉及到类的构造器、静态方法以及线程安全的考虑。 1. **单例模式的核心思想** - **唯一性**:保证类只有一个实例,避免多个实例导致资源浪费或状态不一致。 - **全局访问点**:提供...
Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它描述了在多线程环境下,如何保证各个线程对共享数据的一致性视图。JMM的主要目标是定义程序中各个变量的访问规则,以及在...
然而在Java中,早期的DCL实现并不完全正确,因为Java内存模型的细节可能导致非线程安全。正确的DCL实现需要使用volatile关键字: ```java public class DoubleCheckSingleton { private volatile static ...