您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

java双重检验锁模式是什么

2024/4/16 17:27:05发布5次查看
起因在对项目进行pmd静态代码检测时,遇到了这样一个问题
partially created objects can be returned by the double checked locking pattern when used in java. an optimizing jre may assign a reference to the baz variable before it calls the constructor of the object the reference points to.
note: with java 5, you can make double checked locking work, if you declare the variable to be volatile.
可能在使用双重检验锁模式时,会返回一个未完全初始化的对象。有些人可能会怀疑部分初始化对象的概念,请继续往下分析
什么是双重检验锁模式public static singleton getsingleton() {
    if (instance == null) {                        
        synchronized (singleton.class) {
            if (instance == null) {                 
                instance = new singleton();
            }
        }
    }
    return instance ;

我们看到,在同步代码块的内部和外部都判断了instance == null,这是因为,可能会有多个线程同时进入到同步代码块外的if判断中,如果在同步代码块内部不进行判空的话,可能会初始化多个实例。 
问题所在这种写法看似完美无缺,但它却是有问题的,或者说它并不担保一定完美无缺。主要原因在于instance = new singleton();并不是原子性的操作。
创建一个对象可以分为三部:
1.分配对象的内存空间
2.初始化对象
3.设置instance指向刚分配的内存地址
当instance指向分配地址时,instance是不为null的 
但是,2、3步之间,可能会被重排序,造成创建对象顺序变为1-3-2.试想一个场景:
线程a第一次创建对象singleton,对象创建顺序为1-3-2;
当给instance分配完内存后,这时来了一个线程b调用了getsingleton()方法
这时候进行instance == null的判断,发现instance并不为null。
但注意这时候instance并没有初始化对象,线程b则会将这个未初始化完成的对象返回。那b线程使用instance时就可能会出现问题,这就是双重检查锁问题所在。 
使用volatile对于上述的问题,我们可以通过把instance声明为volatile型来解决
public class singleton{
    private volatile static singleton instance;
    public static singleton getsingleton() {
        if (instance == null) {                        
            synchronized (singleton.class) {
                if (instance == null) {                 
                    instance = new singleton();
                }
            }
        }
        return instance ;
    }

但是必须在jdk5版本以上使用。 
静态内部类public class singleton {  
    private static class singletonholder {  
        private static final singleton instance = new singleton();  
    }  
    private singleton (){}  
    public static final singleton getinstance() {  
        return singletonholder.instance; 
    }  
}
目前比较推荐的写法是采用静态内部类的方式,既能够实现懒加载,又不会出现线程安全问题。而且减少了synchronized的开销。
以上就是java双重检验锁模式是什么的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录