懒汉式创建单例模式线程安全问题

一、synchronized加锁
    

public class Student {
    
        private static Student student;

        private Student(){}

        public static synchronized Student getInstance(){
            if (student == null) {
                student = new Student();
            }

            return student;
        }
    }


    这种方法可以保证线程安全,但性能会非常差,特别是在并发情况下,当一个线程执行这个方法的时候,其他线程都会被阻塞(JDK1.6之前,1.6之后会进行自旋,利用CAS操作不断获取锁,次数不一定(自适应自旋锁),仍获取不到锁后才会阻塞)。
 二、

    public class Student {
    
        private static Student student;

        private Student(){}

        public static Student getInstance(){
            if (student == null) {
                synchronized (Student.class){
                    student = new Student();
                }
            }
            return student;
        }
    }


    这种方法只有在student对象为空时才会创建对象,细化了锁的力度,但在并发情况下,线程A,B同时执行这个方法,同时进行判断,都不为空,A线程得到锁,初始化,B线程自旋,等A线程释放锁后,B线程接着进行初始化,A  B两个线程得到的不是同一个对象。
三、

    public class Student {
    
        private static Student student;

        private Student(){}

        public static Student getInstance(){
            if (student == null) {
                synchronized (Student.class){
                    if (student == null) {
                        student = new Student();
                    }
                }
            }
            return student;
        }
    }


    那利用双重检查判断会怎么样呢?B线程得到锁后初始化前仍会判断student对象是否为空,这时student对象已经初始化了,判断结果为false,B不会再次创建对象。解决了线程安全问题。
四、真的是这样么?
    创建一个对象分为三步
        1.分配内存空间
        2.初始化对象
        3.将内存空间的地址赋值给对象的引用。
            *其中2、3步执行时虚拟机是会重排序的。
        若A线程执行时JVM将2 3步重排序,那么此时对象的易用指向的内存空间仅仅只是一个地址,这时候B线程进行第一次为空判断时,发现不为空,会将对象的引用返回。
    既然错误是由指令重排序造成的,那么我们只有禁止JVM对这个对象创建时指令重排序即可。可以使用volatile关键字。

    public class Student {
    
        private static volatile Student student;

        private Student(){}

        public static Student getInstance(){
            if (student == null) {
                synchronized (Student.class){
                    if (student == null) {
                        student = new Student();
                    }
                }
            }
            return student;
        }
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值