懒汉式单例模式可能存在线程安全问题

戚薇 Java教程 发布时间:2023-06-16 15:13:08 阅读数:10884 1
下文笔者讲述创建单例模式时--线程安全的注意事项分享,如下所示

一.在方法上加上synchronized锁的单例模式

public class SingleteExample {
    private static SingleteExample singleteExample;
    private SingleteExample() {
    } 
	
	public synchronized static SingleteExample getInstance() {
	   if (singleteExample == null) {
            singleteExample = new SingleteExample();
        }
        return singleteExample;
    }
}
 此方式创建的单例模式
     可保证线程安全
     但性能会非常差
     在并发情况下,其他线程会被阻塞

二.在代码块上使用synchronized加锁

public class SingleteExample2 {
    private static SingleteExample2 singleteExample;
    private SingleteExample2() {
    }
    public  static SingleteExample2 getInstance() {
        if (singleteExample == null) {
            synchronized (SingleteExample2.class) {
               singleteExample = new SingleteExample2();
            }
        }
        return singleteExample;
    }
}
  这种方法只有在SingleteExample2对象为空时才会创建对象
   锁的力度更细
  但在并发情况下
    线程A,B同时执行这个方法
    同时进行判断,都为空,A线程得到锁,初始化,
     B线程等A线程释放锁后
     B线程接着进行初始化
     A  B两个线程得到的不是同一个对象。

三.双重检查

public class SingleteExample3 {
    private static SingleteExample3 singleteExample;
 
    private SingleteExample3() {
    }
 
    public static SingleteExample3 getInstance() {
        if (singleteExample == null) {
            synchronized (SingleteExample3.class) {
                if (singleteExample == null) {
                    singleteExample = new SingleteExample3();
                }
            }
        }
        return singleteExample;
    }
}
    B线程得到锁后初始化前仍会判断SingleteExample3对象是否为空
    这时SingleteExample3对象已经初始化了,判断结果为false
     B不会再次创建对象 

四.指令重排序

创建一个对象分为三步 
   1.分配内存空间 
   2.初始化对象 
   3.将内存空间的地址赋值给对象的引用。
   
   其中2、3步执行时虚拟机是会重排序的
	   若A线程执行时JVM将2 3步重排序
	    那么此时对象的引用指向的内存空间仅仅只是一个地址,
       这时候B线程进行第一次为空判断时,发现不为空,会将对象的引用返回
	   使用volatile关键字可禁止JVM重排序
 
public class SingleteExample4 {
    private static volatile SingleteExample4 singleteExample; 
      private SingleteExample4() {
        }
      public static SingleteExample4 getInstance() {
        if (singleteExample == null) {
            synchronized (SingleteExample4.class) {
                if (singleteExample == null) {
                    singleteExample = new SingleteExample4();
                }
            }
        }
        return singleteExample;
    }
}
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaCourse/202306/6806.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者