• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
xiaoyaovo
博客园    首页    新随笔    联系   管理    订阅  订阅
懒汉设计模式使用 volatile 关键字和两个 if 判断的原因

懒汉设计模式

代码

class Singleton {
    // 3. 加 volatile 关键字
    volatile private static Singleton instance = null;


    public static Singleton getInstance() {
    	// 2. 外层判断
        if (instance == null) {
        	// 1. 内层加锁判断
			synchronized (Singleton.class) {
				if (instance == null) {				
					instance = new Singleton();
				}
			}
		}
    }

    private Singleton() {

    }
}

为什么使用 volatile 和两个 if 判断?

  1. 内层加锁判断:在内层中加了 synchronized 锁判断 if (instance == null) ,是为了 防止 两个线程在同一时间调用 getInstance() , 然后判断结果为实例都为 null,从而导致两个线程都创建了实例;
  2. 外层判断:而外层 if (instance == null) 则是防止之后其他线程创建连接都需要加锁进行判断,线程之间的执行方式变成了串行, 时间效率大大变低。因此直接先判断 instance == null ,如果不等于 null,也就说之前已经创建过了实例,那么 直接返回实例
  3. 加 volatile 关键字:根据 2. 外层判断 中得知,如果开始有线程创建实例后,那么后续的线程只需要判断第一层循环即可,因为开始有线程已经把 instance 实例对象写入到内存了。
    但是还是存在一个问题,如果后续线程在 cpu 执行的时候,直接到 cpu 的寄存器查找 instance,判断其是否为 null,发现还是 null,那么就进入内层判断(当然,进入内层的判断是 synchronized 修饰的,已经保证了内存的可见性,因此不会创建新的 instance 实例),这就是内存可见性的问题。因此需要在 instance 对象前加 volatile 关键字保证内存可见性!
posted on 2021-08-14 17:04  豆本豆红枣豆奶  阅读(19)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3