等待唤醒规范化之Guarded Suspension模式

Guarded Suspension模式

什么是Guarded Suspension模式

Guarded Suspension直译为保护性挂起,其核心是一个受保护的方法,该方法在执行其所需要真正执行的操作时需要满足特定的条件,当条件状态不满足时,执行受保护方法的线程挂起并进入等待状态,直到条件状态满足该线程才能继续执行。

现实场景

在我们生活中其实有很多这种场景例如,我们去外面用餐提前在网上预定了一个包间,然后到时间过去用餐,找到大堂经理这时经理发现包间还没收拾,就叫服务员马上收拾,让我们稍等片刻,大堂经理发现服务员收拾完毕后就会将我们带到指定包间,这个过程就是一个典型的Guarded Suspension模式。

这时我们可以将处理流程结构化如下所示

我们需要注意的是Guarded Suspension模式的条件变量这里指的就是餐厅是否打扫干净这个条件。

image-20220312172235148

场景语义化如下

// 大堂经理
class GuardedObject<T> {
    // 受保护对象 餐厅
    private T obj;
    private final Lock lock = new ReentrantLock();

    private final Condition done = lock.newCondition();

    public GuardedObject(T obj){
        this.obj = obj;
    }

    // 获取受保护对象
    public T get(Predicate<T> p){
        lock.lock();
        try {
            while (!p.test(obj)){
                System.out.println("====大堂经理询问是否可以就餐====");
                done.await(1, TimeUnit.SECONDS);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return obj;
    }
	// 给服务员用,打扫完包间就将包间的状态改为干净
    public void onChanged(T obj){
        lock.lock();
        try {
            this.obj = obj;
            done.signalAll();
        }finally {
            lock.unlock();
        }
    }
}

测试代码如下

public static void main(String[] args) throws InterruptedException {
    // obj=1表示餐厅还没收拾  obj=0表示收拾好了可以用餐
    GuardedObject<Integer> guardedObject = new GuardedObject(1);

    // 顾客就餐
    Thread t1 = new Thread(()->{
        System.out.println(Thread.currentThread().getName()+"==顾客进入餐厅");
        // d
        Integer integer = guardedObject.get(e -> {
            return 0 == e;
        });
        System.out.println(Thread.currentThread().getName()+"==顾客可以用餐");
    });

    // 服务员打扫
    Thread t2 = new Thread(()->{
        try {
            System.out.println(Thread.currentThread().getName()+"==服务员开始打扫");
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        guardedObject.onChanged(0);
        System.out.println(Thread.currentThread().getName()+"==服务员打扫完毕");
    });

    t1.start();
    Thread.sleep(500);
    t2.start();

    t1.join();
    t2.join();
}

执行结果如下

image-20220312172916136

总结

Guarded Suspension模式其本质就是等待唤醒机制的一种规范,如果解决实际问题需要或多或少的对Guarded Suspension功能进行扩展(一般是多一个等待队列,任务按照顺序出队处理)。

Guarded Suspension又被称为Guarded Wait 模式、Spin Lock 模式(因为使用了 while 循环去等待),多线程版本if(单线程场景中if语句不需要等待主线程阻塞将没有线程执行了,if判断条件也不会发生变化,而多线程下当前线程的判断结果是有可能被别的线程所篡改的)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值