并发编程模式 - Balking模式

    多线程情况下,定时判断文本、编辑器【如CSDN、Processon等】是否修改过,如果有修改过则进行保存,类似这样的场景称为Balking模式。特点:

1、可以将表示修改的方法用synchronized或者Lock修饰

2、使用volatile修饰,没有原则性要求。比如 Dubbo负载均衡会将服务的列表同步到本地,定时查询是否发送了变化

3、还有一种无所的方式,volatile + 双重锁(Double Check)检查机制的单利实现

 

传统的Balking模式写法如下:

public class ClassicBalking {
    boolean changed = false;
    ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
    /**
     *   启动字段保存方法
     */
    void startAutoSave() {
        service.scheduleWithFixedDelay(() -> {
            // 自动保存
            autoSave();
            // 每5秒钟字自动保存一次
        }, 5, 5, TimeUnit.SECONDS);
    }

    private void autoSave() {
        synchronized (this) {
            if (!changed) {
                return;
            }
            changed = false;
        }
        System.out.println("我保存了");
    }

    private void edit() {
        synchronized (this) {
            changed = true;
        }
    }

}

 

    线程安全问题需要注意,原子性、可见性、有序性。但是使用双重锁检查机制并不能完全解决,所以需要增加 volatile关键字修饰,如下图:

/**
 *  双重锁检查方式,初始化单例,  如果想防止指令重拍序则在instance上加一个 volatile 关键字即可
 *  <p>
 *      编译器优化【只保证在单线程下执行的结果一致】之后,可能的结果:
 *      1、将多条语句位置替换
 *      如: int a = 1;int b = 2; 优化为:int b = 2; int a = 1;  // 单线程下是ok的
 *      2、将高级语言Java的底层一条语句,对于的多条CPU指令进行重拍序下,如下面的双重锁检查
 *         可能在【singleton = new Singleton();】对象时的三个指令,重拍序之后可能把2和3颠倒
 *      如:1)、分配一块内存M
 *          2)、在内存M上初始化Singleton对象
 *          3)、将M地址赋值给instance对象
 *
 *  <p>
 *      可能的问题:
 *      线程A执行到把 【M地址赋值给Instance】但是还没有真正创建对象时发生线程切换,
 *      线程B在第一处的判断instance是否为null,不为null, 直接返回。使用时却发生了NPE
 *
 * @author kevin
 * @date 2020/7/26 18:26
 * @since 1.0.0
 */
public class Singleton {

    /**
     *  单例对象
     */
    private static volatile Singleton singleton;

    /**
     *  对外提供的单例对象,需要保证只初始化一次,每次获取同一对象
     */
    public Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    /**
     *  构造私有化
     */
    private Singleton() {
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值