Java单例的由浅入深----懒汉式的升级(2 原子操作、指令重排)懒汉式的最终版本(volatile)

知识点:什么是原子操作

简单的来说,原子操作(atomic)就是不可分割的操作,在计算机中,就是指不会因为线程调度被打断的操作。
比如,简单的赋值就是一个原子操作

m=6;

例如m原先的值为0,那么对于这个操作,要么执行成功变成了6,要么执行失败变成了0,而不会出现诸如m=3这种中间状态–即使是在并发的线程中。
然而声明赋值就不是一个原子操作:

int m = 6;

对于这个语句,至少有两个操作:
1、声明一个变量m
2、给m赋值为6
这样就会有一个中间状态:变量m已经被申明了但是还没有赋值
所以,这种状况在多线程中,由于线程执行的不确定性,如果两个线程都使用m,就可能倒是不稳定的结果出现

知识点:什么是指令重排

简单的来说:就是计算机为了提高执行效率,会做一些优化,在不影响最终结果的情况下,可能会对一些语句的执行顺序进行调整。
比如:

int a;//语句1
a=8;//语句2
int b =9; //语句3
int c =a+b;//语句4

正常来说,对于顺序结构,执行的顺序是自上到下
但是,由于指令重排,因为不影响最终结果,所以执行的顺序很可能编程3124,或者1234
由于3,4没有原子性问题,语句3,4可能会被拆分成原子操作,再重排。
也就是说,对于非原子性操作,在不影响结果的情况下,其拆分成的原子操作可能会重排执行顺序

所以在博客1中的懒汉式代码中 singleton = new Singleton()这句,这并非是一个原子操作,事实上在JVM中这句话大概做了下面3件事情
1.给singleton分配内存
2.调用Singleton的构造函数来初始化成员变量
3.将singleton对象指向分配的内存空间(执行到这一步,singleton才是非null的了)
但是在JVM的及时编译器中,存在指令重拍的优化,也就是说,第二步和第三步的顺序是无法保证的
而导致程序出错
所以我们拥有了一个最终版本

3.4终极版本:volatile

public class Singleton {
    private static volatile Singleton singleton;

    private Singleton() {
    }
    public static Singleton getsingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}

volatile关键字的作用是禁止指令重排,把singleton声明为volatile之后,对它的写操作就会有一个内存屏障,这样,在它完成赋值之前,就不会调用读的操作了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值