53.Java-单例

  • 饿汉模式
class Person{
    //私有化构造器
    private Person() {
            
    }
        
    private static Person instance = new Person();
        
    public static Person getInstance() {
        return instance;
    }
}
  • 懒汉模式

非安全模式下的懒汉模式

class Person{
    private Person() {
        
    }
    
    private static Person instance = null;
    
    public static Person getInstance() {
        if (instance == null) {
            instance = new Person();
        }
        return instance;
    }
}

安全模式

class Person{
    private Person() {
        
    }
    
    private static Person instance = null;
    
    public synchronized static Person getInstance() {
        if (instance == null) {
            instance = new Person();
        }
        return instance;
    }
}

该安全模式使用同步方法,已经解决了线程安全问题
但是synchronized的作用域太大,损耗性能-->尽量减小synchronized的作用域
解决方案:使用双重检查锁机制
双重检查锁:

可以使用"双重检查锁"的方式来实现,就可以即实现线程安全,又能够使性能不受太大影响,那什么是"双重检查锁"机制呢?

所谓"双重检查锁"机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在再进行下面的同步块,这是第一重检查,进入同步后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查,这样一来,就只需要同步一次了,从而减少了多次在同步的情况下进行判断所浪费的时间.

"双重检查锁"机制的实现会使用关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

注意:在java1.4及以前版本中,很多关键字对于volatile的实现问题,会导致"双重检查锁"的失败,因此"双重检查锁"机制只能用在java5及以上的版本.

提示:由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高,因此一般建议,没有特别的需要,不要使用,也就是说,虽然可以使用"双重检查锁"机制来实现线程安全的单例,但是并不建议大量采用,可以根据情况来选用

class Person{
    private Person() {
        
    }
    
    private static Person instance = null;
    
    public static Person getInstance() {
        if (instance == null) {
            synchronized(Person.class){
                if (instance == null) {
                    instance = new Person();
                }
            }
        }
        return instance;
    }
}


你可能感兴趣的:(53.Java-单例)