`

JAVA 单例模式与多线程

    博客分类:
  • JAVA
阅读更多
单例模式单例模式是一种常见的设计模式,
单例模式分三种:懒汉式单例、饿汉式单例、内部类单例、登记式单例几种。
单例模式有一下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
懒汉模式不是线程安全的。
饿汉模式是线程安全的。
内部内模式利用Classloader的特
注册表模式是线程安全的同时又提供运行期指定单例。
饿汉式单例类
public class Singleton    
{    
    private Singleton(){    
        
     }    
   
    private static Singleton instance = new Singleton();    
   
    private static Singleton getInstance(){    
        return instance;    
     }    
}   


内部类式单例类
public class Singleton      
{         
        private Singleton(){      
          
     }      
     
    private class SingletonHoledr(){      
        private static Singleton instance = new Singleton();      
     }      
     
    private static Singleton getInstance(){      
        return SingletonHoledr.instance;      
     }      
}   
懒汉式单例类

可以同步但是效率不高:

Java代码
public class Singleton       
{          
    private Singleton(){       
      
     }       
      
    private static Singleton instance;       
    public static synchronized Singleton getInstance(){       
        if(instance == null){       
            return instance = new Singleton();       
         }else{       
            return instance;       
         }       
     }       
}     
 

这样写程序不会出错,因为整个getInstance是一个整体的"critical section",但就是效率很不好,因为我们的目的其实只是在第一个初始化instance的时候需要locking(加锁),而后面取用instance的时候,根本不需要线程同步。
于是聪明的人们想出了下面的做法:

双检锁写法:

Java代码
public class Singleton{    
  private static Singleton single;    //声明静态的单例对象的变量    
  private Singleton(){}    //私有构造方法    
      
  public static Singleton getSingle(){    //外部通过此方法可以获取对象      
    if(single == null){       
        synchronized (Singleton.class) {   //保证了同一时间只能只能有一个对象访问此同步块          
            if(single == null){        
                 single = new Singleton();            
         }       
       }    
     }      
    return single;   //返回创建好的对象    
   }    
}  


public class Singleton{
   private static Singleton single;     //声明静态的单例对象的变量
   private Singleton(){}     //私有构造方法 
   
   public static Singleton getSingle(){     //外部通过此方法可以获取对象  
     if(single == null){    
          synchronized (Singleton.class) {    //保证了同一时间只能只能有一个对象访问此同步块       
              if(single == null){     
                  single = new Singleton();          
         }    
       }
     }  
     return single;    //返回创建好的对象 
   }
}
思路很简单,就是我们只需要同步(synchronize)初始化instance的那部分代码从而使代码既正确又很有效率。
这就是所谓的“双检锁”机制(顾名思义)。
很可惜,这样的写法在很多平台和优化编译器上是错误的。

原因在于:instance = new Singleton()这行代码在不同编译器上的行为是无法预知的。一个优化编译器可以合法地如下实现instance = new Singleton():

1. instance = 给新的实体分配内存

2. 调用Singleton的构造函数来初始化instance的成员变量

现在想象一下有线程A和B在调用getInstance,线程A先进入,在执行到步骤1的时候被踢出了cpu。然后线程B进入,B看到的是instance 已经不是null了(内存已经分配),于是它开始放心地使用instance,但这个是错误的,因为在这一时刻,instance的成员变量还都是缺省值,A还没有来得及执行步骤2来完成instance的初始化。

当然编译器也可以这样实现:

1. temp = 分配内存

2. 调用temp的构造函数

3. instance = temp

如果编译器的行为是这样的话我们似乎就没有问题了,但事实却不是那么简单,因为我们无法知道某个编译器具体是怎么做的,因为在Java的memory model里对这个问题没有定义。

双检锁对于基础类型(比如int)适用。很显然吧,因为基础类型没有调用构造函数这一步。
http://hi.baidu.com/rtsbtx/blog/item/80c9693b306e1ee114cecb5e.html
分享到:
评论

相关推荐

    java单例模式实例

    在多线程环境下,可能会创建多个实例。例如: ```java public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == ...

    Java 单例模式.pptx

    - **线程安全问题**:懒汉式单例模式在多线程环境下可能会导致创建多个实例,因此需要采用同步机制保证线程安全,例如使用`synchronized`关键字。 - **静态内部类方式** - **实现**: ```java class Single3 {...

    Java 单例模式 懒汉模式

    Java 单例模式 懒汉模式 //懒汉式 多线程中不可以保证是一个对象

    Java多线程实战之单例模式与多线程的实例详解

    Java多线程实战之单例模式与多线程的实例详解 单例模式是Java多线程编程中最常用的设计模式之一,它的主要作用是确保一个类在应用程序中只有一个实例,并提供一个全局访问点。单例模式有多种实现方式,如饿汉模式、...

    Java 单例模式线程安全问题

    然而,在多线程环境下,单例模式可能会遇到线程安全问题,因为多个线程可能会同时访问同一个实例,从而导致数据不一致和其他问题。 在 Java 中,单例模式的实现可以使用双重检查锁机制、静态内部类和枚举类型等方式...

    使用Java单例模式实现一个简单的日志记录器.txt

    ### 使用Java单例模式实现一个简单的日志记录器 #### 一、单例模式简介 单例模式是一种常用的软件设计模式,在该模式中,一个类只能创建一个实例,并且提供了一个全局访问点来访问该实例。单例模式的主要优点包括...

    Java单例模式设计

    Java单例模式是一种常用的设计模式,它保证一个类只有一个实例,并提供全局访问点。这种模式在需要频繁创建和销毁对象的场景中,或者当对象昂贵时(如数据库连接),能够节省系统资源,提高效率。本篇文章将深入探讨...

    Java单例模式深入理解

    Java单例模式是一种设计模式,它允许在程序中创建唯一一个类实例,通常用于管理共享资源,例如数据库连接、线程池或者配置对象等。单例模式的核心在于限制类的构造函数,确保类只能被初始化一次,从而实现全局唯一的...

    JAVA单例模式的几种实现方法

    ### JAVA单例模式的几种实现方法 #### 一、饿汉式单例类 饿汉式单例类是在类初始化时就已经完成了实例化的操作。这种实现方式简单且线程安全,因为实例化过程是在编译期间完成的,不会受到多线程的影响。 **代码...

    Java单例模式应用研究.pdf

    ### Java单例模式应用研究 #### 一、单例模式概述 单例模式(Singleton Pattern)作为一种最基本的创建型设计模式,其主要目的是控制一个类的实例化过程,确保在整个应用程序中仅存在一个实例,并且该实例能够被全局...

    Java实现多种单例模式

    在Java编程中,单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在需要频繁创建和销毁对象的场景中尤其有用,因为它可以节省系统资源并确保对象间的协调一致。以下是...

    java单例模式连接数据库源码

    Java单例模式是一种设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在数据库连接管理中,使用单例模式能有效控制资源,避免频繁创建和关闭数据库连接导致的性能损失和资源浪费。以下是对Java单例模式...

    java单例模式的例子

    Java单例模式是一种常见的设计模式,它在软件工程中用于控制类的实例化过程,确保一个类只有一个实例,并提供一个全局访问点。这种模式在系统资源管理、缓存、日志记录等方面应用广泛。下面我们将深入探讨Java单例...

    java设计模式之单例模式.zip

    这些视频可能涵盖了单例模式的基本概念、实现方式、优缺点、适用场景以及可能遇到的问题,如序列化时如何保持单例、如何在多线程环境下正确实现单例等。观看这些视频,可以更深入地理解并掌握Java中的单例模式,从而...

    多线程单例模式并发访问

    #### 二、多线程与CPU交互机制 在多线程环境中,线程与CPU之间的交互机制非常重要。线程间的资源竞争导致了线程调度的重要性。操作系统通过调度算法来决定哪个线程获得CPU时间片,从而实现多线程程序的高效运行。 -...

    浅议单例模式之线程安全(转)

    在多线程环境下,线程安全的单例模式尤为重要,因为如果不正确实现,可能会导致多个线程同时创建多个实例,违反了单例模式的基本原则。 在Java中,单例模式通常有以下几种实现方式: 1. 饿汉式(静态常量): ...

Global site tag (gtag.js) - Google Analytics