美文网首页
Balking模式:再谈线程安全的单例模式

Balking模式:再谈线程安全的单例模式

作者: woshishui1243 | 来源:发表于2019-12-05 15:18 被阅读0次

Guarded Suspension 模式需要等待的,必须要等到条件为真。但有些场景下,我们需要快速放弃。最常见的例子是各种编辑器提供的自动保存功能。自动保存功能的实现逻辑一般都是隔一定时间自动执行存盘操作,存盘操作的前提是文件做过修改,如果文件没有执行过修改操作,就需要快速放弃存盘操作。

class AutoSaveEditor{
  // 文件是否被修改过
  boolean changed=false;
  // 定时任务线程池
  ScheduledExecutorService ses = 
    Executors.newSingleThreadScheduledExecutor();
  // 定时执行自动保存
  void startAutoSave(){
    ses.scheduleWithFixedDelay(()->{
      autoSave();
    }, 5, 5, TimeUnit.SECONDS);  
  }
  // 自动存盘操作
  void autoSave(){
    synchronized(this){
        if (!changed) {
          return;
        }
        changed = false;
    }
    // 执行存盘操作
    // 省略且实现
    this.execSave();
  }
  // 编辑操作
  void edit(){
    // 省略编辑逻辑
    ......
    synchronized(this){
        changed = true;
    }
  }
}

示例中的共享变量是一个状态变量,业务逻辑依赖于这个状态变量的状态:当状态满足某个条件时,执行某个业务逻辑,其本质其实不过就是一个 if 而已,放到多线程场景里,就是一种“多线程版本的 if”。这种“多线程版本的 if”的应用场景还是很多的,所以也有人把它总结成了一种设计模式,叫做Balking 模式

Balking 模式的实现

  1. Balking 模式的经典实现是使用互斥锁,你可以使用 Java 语言内置 synchronized,也可以使用 SDK 提供 Lock
  2. 用 volatile 实现 Balking 模式,但使用 volatile 的前提是对原子性没有要求。

Balking 模式的应用

Balking 模式有一个非常典型的应用场景就是单次初始化,下面的示例代码是它的实现。这个实现方案中,我们将 init() 声明为一个同步方法,这样同一个时刻就只有一个线程能够执行 init() 方法;init() 方法在第一次执行完时会将 inited 设置为 true,这样后续执行 init() 方法的线程就不会再执行 doInit() 了。

class InitTest{
  boolean inited = false;
  synchronized void init(){
    if(inited){
      return;
    }
    // 省略 doInit 的实现
    doInit();
    inited=true;
  }
}

线程安全的单例模式本质上其实也是单次初始化,所以可以用 Balking 模式来实现线程安全的单例模式。

class Singleton{
  private static volatile 
    Singleton singleton;
  // 构造方法私有化  
  private Singleton() {}
  // 获取实例(单例)
  public static Singleton 
  getInstance() {
    // 第一次检查
    if(singleton==null){
      synchronize{Singleton.class){
        // 获取锁后二次检查
        if(singleton==null){
          singleton=new Singleton();
        }
      }
    }
    return singleton;
  }
}

相关文章

  • Balking模式:再谈线程安全的单例模式

    Guarded Suspension 模式需要等待的,必须要等到条件为真。但有些场景下,我们需要快速放弃。最常见的...

  • 设计模式

    手写单例模式(线程安全) 你知道几种设计模式?单例模式是什么?Spring中怎么实现单例模式?

  • 设计模式——单例模式

    单例模式 饿汉模式 懒汉模式 线程不安全的模式 线程安全模式 懒汉模式和饿汉模式的区别

  • 单例设计模式笔记

    记录几种单例模式写法。 饿汉模式(线程不安全) 懒汉模式(线程不安全) 懒汉锁模式(线程安全) 懒汉双重判断模式(...

  • 设计模式(2) 单例模式

    单例模式 线程安全的Singleton 会破坏Singleton的情况 线程级Singleton 单例模式是几个创...

  • 面试复习-设计模式

    一、单例模式 确保一个类只有一个实例,并提供一个全局访问点。 线程不安全的单例模式 懒汉式 线程安全的单例模式: ...

  • Java 常用单例

    一、线程不安全的单例模式 二、线程安全且高效的单例模式 1.双重校验锁 2.静态内部类

  • Java设计模式(一)

    talk is cheap show me the code 单例模式 懒汉模式 恶汉模式 线程安全模式 工厂模式...

  • Java 单例模式

    概述 Java中单例模式是一种常见的设计模式,单例模式总共有7种写法。 懒汉,线程不安全 懒汉,线程安全 饿汉 饿...

  • Singleton 单例模式

    饿汉式单例模式 饿汉式单例模式 通过静态代码块增加异常处理 懒汉式单例模式 存在线程安全问题 懒汉式单例模式 解决...

网友评论

      本文标题:Balking模式:再谈线程安全的单例模式

      本文链接:https://www.haomeiwen.com/subject/snidgctx.html