单例模式这样写比较严谨

15 篇文章 0 订阅
2 篇文章 0 订阅

我先贴出正确的写法,在分析(注意标红部分):


注意点已经在代码标红,下面分析巧妙之处:

(1) 避免锁定整个 getInstance() ,如果锁定整个获取实例的方法,那么多线程每次获取的时候,都有可能等待,等其他线程执行完,会有性能的损失。所以在先在(1)处判断一下,非空的话,直接拿出来用。

(2)第二个if(instance==null) 是因为,进入同步块的时候,可能其他线程已经创建完毕,所以再判断一下。

(3)volatile 的作用是多线程之间,保证变量instance的可见性,避免因为每个线程的工作内存里面的变量instance 的值不同而取脏数据。这里我简单说一下工作内存:每个线程有自己的工作内存的,如果工作内存没有它要用的对象,它会到主内存去读,它更新这个对象的时候,它会先写到工作内存,然后再写到主内存。由于每个线程都有自己的工作内存,所以可能会读脏数据。当对象加了volatile ,就会保证 该对象一旦改变,会写到主内存,并且通知其他线程到主内存去读。

instance = new Singleton();  这句在执行的时候,可以分解为3行伪代码如下:

1 memory=allocate();// 分配内存 相当于c的malloc

2 ctorInstanc(memory) //初始化对象

3 instance=memory //设置instance指向刚分配的地址


上面的代码在编译器运行时,可能会出现重排序 从1-2-3 排序为1-3-2

如此在多线程下就会出现问题

例如现在有2个线程A,B

线程A在执行new Singleton()时,B线程进来,而此时A执行了 1和3,没有执行2,此时B线程判断instance不为null (分配了空间即非空,但是对象还没初始化), 直接返回一个未初始化的对象,就会出现问题

而用了volatile,上面的重排序就会在多线程环境中禁止,不会出现上述问题。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值