对于volatile双重校验锁的理解。

对于懒汉式创建单例对象的时候,我们会发现它会进行两次判断改对象是否为null。其实我们完全可以对该构造方法直接加锁,这样就保证了该对象的完全单例。但是这样就有个问题,以后每次我调用构造方法的时候,我都会去加锁,其实加锁的目的是为了防止第一次创建对象的线程安全,后续我想要获得单例对象就不需要进行加锁控制了。所以这样做的话会影响性能。

那么第二种做法就是,降低锁的粒度,也就是所谓的双重校验锁。我们在进入构造方法的时候,先进行一次判断,如果不为空则直接返回,此时并没有加锁,是为了解决上述已经完成单例对象的创建,后续则都可以简单的通过这个if判断来拿到单例对象,如果是第一次创建,有两个线程同时进来,那第一个if就是不安全的状态了。此时进入同步代码块儿,我们需要立马进行第二次非空判断。来防止两个线程都进入同步代码块儿进行对象的创建。通过这样的方式,即使第二个线程进同步代码块儿,也会因为if判断而退出直接返回对象。那么这里又有一个细节就是,我们需要对我们的单例对象加上volatile修饰,否则就会产生这样一个现象。我先说一下volatile的作用吧,这里他的作用是为了防止jvm对该对象创建的字节码指令进行优化重排序,他其实是为了防止在同步代码块儿时候的判断,当第一个线程进入代码块儿进行对象的创建。而第二个线程进入外层if的判断。此时该对象假如还没有进行玩对象的初始化过程,但是因为指令重排序,可能会导致没完成初始化就返回了该对象的地址,所以第二个线程发现该对象不为空,就会直接返回对象并使用,但是因为没有进行玩初始化,则该线程在使用的过程中可能会出现一些异常。

posted on 2022-07-04 13:40  波波头  阅读(98)  评论(0)    收藏  举报