Java-多线程与单例

最近在公司写需求时遇到了多线程与单例一同出现的状况。安全

这个时候想到的就是线程安全以及单例的定义了,虽然单例指的是在内存中它只有一份,可是并非说就是线程安全的。多线程

因此,我当时就到网上找了关于多线程下单例的线程安全问题的资料,而后就知道以下博客:高并发下线程安全的单例模式(最全最经典)并发

其中,博主最推荐的写做方式以下:高并发

为了达到线程安全,又能提升代码执行效率,这里能够采用DCL(Double Check Locking)的双检查锁机制来完成

public class MySingleton {  
      
    //使用volatile关键字保其可见性  
    volatile private static MySingleton instance = null;  
      
    private MySingleton(){}  
       
    public static MySingleton getInstance() {  
        try {    
            if(instance != null){//懒汉式   
                  
            }else{  
                //建立实例以前可能会有一些准备性的耗时工做   
                Thread.sleep(300);  
                synchronized (MySingleton.class) {  
                    if(instance == null){//二次检查  
                        instance = new MySingleton();  
                    }  
                }  
            }   
        } catch (InterruptedException e) {   
            e.printStackTrace();  
        }  
        return instance;  
    }  
} 

看了看内容确实是这个道理,而后就把这段代码拿来使用了。而后在实际测试中发现,其并无保证线程安全的问题。测试

以后在同事的指点下发现,其实上文一段的线程安全仅仅只是在未实例化单例的前提下,以线程安全的方式实例化单例,使之在高并发多线程的环境下有且仅被new过一次。spa

也就是说,在单例被实例化以后,这段代码是并无什么做用的。.net

单例被实例化以后,instance != null一直成立,使getInstance()每次都是return instance。因此,多线程都能拿到指向同一个实例的引用。线程

因此即便是使用了这种双检查锁机制的代码,依然要对后面要使用到的公用方法作同步,以避免出现问题。code

而对公用方法作同步的操做也分两种状况。一种是公用方法里只有局部变量,那么此时不作同步也是能够的,由于局部变量只会存在于相应的线程内存里,并不会被其它线程所影响。另一种是含有成员变量,若是成员变量只有读的操做,那不一样步也能够;若是成员变量涉及读写操做,那么就要对相应的方法进行同步了。对象

局部变量不会受多线程影响
成员变量会受到多线程影响

多个线程应该是调用的同一个对象的同一个方法:
若是方法里无成员变量,那么不受任何影响
若是方法里有成员变量,只有读操做,不受影响
                      存在写操做,考虑多线程影响值

 

来源:关于多个线程同时调用单例模式的对象,该对象中方法的局部变量是否会受多个线程的影响

相关文章
相关标签/搜索