32. Balking模式:再谈线程安全的单例模式 - 并发设计模式 - 待完成

mac2024-12-01  46

文章目录

1. 场景2. Balking模式的经典实现3. 用volatile实现Balking模式

1. 场景

编辑器提供的自动保存功能需要快速放弃:隔一定时间自动执行存盘操作,如果文件没有执行过修改操作,就需要快速放弃存盘操作。

class AutoSaveEditor { // 文件是否被修改过,这个变量没有同步,通过对其加锁来保证类的线程安全 boolean changed = false; // 定时任务线程池 ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); // 定时执行自动保存 void startAutoSave() { ses.scheduleWithFixedDelay(() -> { autoSave(); }, 5, 5, TimeUnit.SECONDS); } // 文件自动存盘操作,读写changed加锁,减少加锁范围 void autoSave() { synchronized(this){ if (!changed) { return; } changed = false; } // 执行存盘操作 // 省略且实现 this.execSave(); } // 编辑操作 void edit(){ //省略编辑逻辑 ...... // 读写changed加锁,减少加锁范围 synchronized(this){ changed = true; } } }

共享变量是一个状态变量,本质上是多线程版本if,有人总结为Balking模式。

2. Balking模式的经典实现

class AutoSaveEditor { // 文件是否被修改过,这个变量没有同步,通过对其加锁来保证类的线程安全 boolean changed = false; // 定时任务线程池 ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); // 定时执行自动保存 void startAutoSave() { ses.scheduleWithFixedDelay(() -> { autoSave(); }, 5, 5, TimeUnit.SECONDS); } // 文件自动存盘操作,读写changed加锁,减少加锁范围 void autoSave() { synchronized(this){ if (!changed) { return; } changed = false; } // 执行存盘操作 // 省略且实现 this.execSave(); } // 编辑操作 void edit(){ //省略编辑逻辑 ...... // 读写changed加锁,减少加锁范围 change(); } private void change() { synchronized(this){ changed = true; } } }

Balking模式本质上是一种规范化地解决“多线程版本的if”的方案,对于上面自动保存的例子,使用 Balking模式规范化之后的写法如下所示,你会发现仅仅是将edit()方法中对共享变量changed的赋值操作抽 取到了change()中,这样的好处是将并发处理逻辑和业务逻辑分开。

3. 用volatile实现Balking模式

最新回复(0)