Double-checked locking should not be used

单例模式,确保一个类只有一个实例,它又分为饿单例模式(类加载时实例化一个对象给自己的引用,如果对象很大是对内存一种巨大的浪费)和懒单例模式(调用取得实例的方法如getInstance时才会实例化对象)。而懒单例模式稍稍复杂下,主要是要考虑两点是否Lazy 初始化和多线程安全。双重检查锁定是在输入同步块之前和之后检查惰性初始化对象的状态以确定对象是否被初始化。如果没有对float或int以外的任何可变实例进行额外的同步,它就不能以平台独立的方式可靠地工作。使用双重检查锁定对任何其他类型的基元或可变对象进行延迟初始化会使第二个线程使用未初始化或部分初始化的成员,而第一个线程仍在创建它,并使程序崩溃。

有多种方法可以解决这个问题。最简单的一种方法是根本不使用双重检查锁定,而是同步整个方法。对于早期版本的JVM,出于性能原因,通常建议不要同步整个方法。但在较新的JVM中,同步性能有了很大的改进,所以现在这是一个首选的解决方案。如果您希望避免同时使用synchronized,那么可以使用内部静态类来保存引用。内部静态类保证可以延迟加载。

//饿单例模式
//是否 Lazy 初始化:否
//是否多线程安全:是
public class Singleton {
    private static Singleton sc  = new Singleton();
    private Singleton(){
    }
    public static Singleton getInstance(){
        return sc;
    }
}
//懒单例模式
//是否 Lazy 初始化:是
//是否多线程安全:是
public class DoubleCheckedLocking {
    private static Resource resource;

    public static Resource getInstance() {
        if (resource == null) {
            synchronized (DoubleCheckedLocking.class) {
                if (resource == null)
                    resource = new Resource();
            }
        }  return resource;
    }

    static class Resource {
    }  
}

兼容性解决方案

@ThreadSafe
public class SafeLazyInitialization {
    private static Resource resource;
    public synchronized static Resource getInstance() {
        if (resource == null)
            resource = new Resource();
        return resource;
    }
    static class Resource {
    }
}
/**
 * With inner static holder:
 */
@ThreadSaf
public class ResourceFactory {
    private static class ResourceHolder {
        // This will be lazily initialised
        public static Resource resource = new Resource();
    }
    public static Resource getResource() {
        return ResourceFactory.ResourceHolder.resource;
    }

    static class Resource {
    }
}
/**
 * Using "volatile":
 */
class ResourceFactory {
    private volatile Resource resource;
    public Resource getResource() {
        Resource localResource = resource;
        if (localResource == null) {
            synchronized (this) {
                localResource = resource;
                if (localResource == null) {
                    resource = localResource = new Resource();
                }
            }
        }
        return localResource;
    }
    static class Resource {
    }
}

see

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值