如何保证单例式或者说一个方法的执行过后,就不会有另外的方法去再次执行了呢,简化的说,就是一个多线程状态下,如何保证一个if

且让这个if 状态是线程安全的

那么,对于一个状态条件的安全性,可以使用一个即为简单的解决方案,就是进行加互斥锁,加互斥锁,下面一个示例代码 可以简单的实现这个解决方案

//自动存盘操作

void autoSave(){

synchronized(this){

if (!changed) {

return;

}

changed = false;

}

//执行存盘操作

//省略且实现

this.execSave();

}

//编辑操作

void edit(){

//省略编辑逻辑

synchronized(this){

changed = true;

}

}

那么针对一个多线程下的if,被总结为了一个设计模式,叫做Balking设计模式

这个设计模式中关于条件变量的修改,将其放置到了一个线程安全的方法之中

将条件变量封装为了一个函数,减少了线程同步消耗

boolean changed=false;

//自动存盘操作

void autoSave(){

synchronized(this){

if (!changed) {

return;

}

changed = false;

}

//执行存盘操作

//省略且实现

this.execSave();

}

//编辑操作

void edit(){

//省略编辑逻辑

change();

}

//改变状态

void change(){

synchronized(this){

changed = true;

}

}

这样就能最小化的将同步线程的消耗降低

接下来可以考虑使用volatile实现Balking

但是使用volatile需要对原子性没有要求,可以保证可见性

那一个场景距离,假设RPC框架可能出现宕机状况,那么需要针对这种极端的情况进行备份管理,在一定情况的时候进行自动保存一次,保存后将是否修改的值置为false

//路由表信息

public class RouterTable {

//Key:接口名

//Value:路由集合

ConcurrentHashMap<String, CopyOnWriteArraySet<Router>> rt = new ConcurrentHashMap<>();

//路由表是否发生变化

volatile boolean changed;

//将路由表写入本地文件的线程池

ScheduledExecutorService ses= Executors.newSingleThreadScheduledExecutor();

//启动定时任务

//将变更后的路由表写入本地文件

public void startLocalSaver(){

ses.scheduleWithFixedDelay(()->{

autoSave();

}, 1, 1, MINUTES);

}

//保存路由表到本地文件

void autoSave() {

if (!changed) {

return;

}

changed = false;

//将路由表写入本地文件

//省略其方法实现

this.save2Local();

}

//删除路由

public void remove(Router router) {

Set<Router> set=rt.get(router.iface);

if (set != null) {

set.remove(router);

//路由表已发生变化

changed = true;

}

}

//增加路由

public void add(Router router) {

Set<Router> set = rt.computeIfAbsent(

route.iface, r ->

new CopyOnWriteArraySet<>());

set.add(router);

//路由表已发生变化

changed = true;

}

}

那么接下里还有就是其契合单例模式,因为单例模式本质上也是单词初始化,可以使用Balking模式来实现线程安全的单例模式

就是在获取到实例之前进行加锁,保证其获取的线程同步性

如果需要进行优化,可以考虑在锁的外面进行一次判断,如果为null在进行获取到锁

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的经典实现方式是互斥锁,Synchronized,当然可以考虑使用Lock和unLock

也可以考虑使用volatile方案,不过需要更加的谨慎罢了

发表评论

邮箱地址不会被公开。 必填项已用*标注