第三部分-并发设计模式32:Balking设计模式
1.Balking模式
线程安全的单例模式
2.多线程的if
多线程if条件快速放弃的方案
3.案例精选
编辑器自动保存功能
每隔一段时间自动执行存盘操作,前提是文件做过修改。如果文件没有做过操作,不要等待,快速放弃存盘。和上一篇的Guarder Suspension在这一点有很大的不同。Guarder Suspension是强制等待,直到条件满足才执行下一步操作。
代码样例:
AutoSaveEditor.java
class AutoSaveEditor{
//文件是否被修改过
boolean changed=false;
//定时任务线程池
ScheduledExecutorService ses =
Executors.newSingleThreadScheduledExecutor();
//定时执行自动保存
void startAutoSave(){
ses.scheduleWithFixedDelay(()->{
autoSave();
}, 5, 5, TimeUnit.SECONDS);
}
//自动存盘操作
void autoSave(){
if (!changed) {
return;
}
changed = false;
//执行存盘操作
//省略且实现
this.execSave();
}
//编辑操作
void edit(){
//省略编辑逻辑
......
changed = true;
}
}
4.以上代码是否是线程安全的?
不是,对共享变量changed的读写没有使用同步
5.如何保证线程安全呢?
方法级加锁,synchronized 修饰,但锁范围太大,性能不好了
如何优化性能?只对共享变量的操作进行加锁,锁的是AutoSaveEditor对象
//自动存盘操作
void autoSave(){
synchronized(this){
if (!changed) {
return;
}
changed = false;
}
//执行存盘操作
//省略且实现
this.execSave();
}
//编辑操作
void edit(){
//省略编辑逻辑
......
synchronized(this){
changed = true;
}
}
6.多线程版本的if,就叫做balking模式
Balking设计模式,本质上是一种规范化解决多线程if的方案。
修改代码,对共享变量changed的赋值操作抽到了change方法中 ,好处是并发处理逻辑和业务逻辑区分开,使得符合Balking设计模式
boolean changed=false;
//自动存盘操作
void autoSave(){
synchronized(this){
if (!changed) {
return;
}
changed = false;
}
//执行存盘操作
//省略且实现
this.execSave();
}
//编辑操作
void edit(){
//省略编辑逻辑
......
change();
}
//改变状态
void change(){
synchronized(this){
changed = true;
}
}
7.单例模式的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;
}
}
8.总结
Balking 模式只需要互斥锁就能解决,而Guarded Suspension 要用管程并发原语。
Guarder Suspension 模式会等待多线程if条件为真,而Balking 模式不会等待,快速放弃。
原创:做时间的朋友