Guarded Suspension模式
什么是Guarded Suspension模式
Guarded Suspension直译为保护性挂起,其核心是一个受保护的方法,该方法在执行其所需要真正执行的操作时需要满足特定的条件,当条件状态不满足时,执行受保护方法的线程挂起并进入等待状态,直到条件状态满足该线程才能继续执行。
现实场景
在我们生活中其实有很多这种场景例如,我们去外面用餐提前在网上预定了一个包间,然后到时间过去用餐,找到大堂经理这时经理发现包间还没收拾,就叫服务员马上收拾,让我们稍等片刻,大堂经理发现服务员收拾完毕后就会将我们带到指定包间,这个过程就是一个典型的Guarded Suspension模式。
这时我们可以将处理流程结构化如下所示
我们需要注意的是Guarded Suspension模式的条件变量这里指的就是餐厅是否打扫干净这个条件。
场景语义化如下
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 {
GuardedObject<Integer> guardedObject = new GuardedObject(1);
Thread t1 = new Thread(()->{
System.out.println(Thread.currentThread().getName()+"==顾客进入餐厅");
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();
}
执行结果如下
总结
Guarded Suspension模式其本质就是等待唤醒机制的一种规范,如果解决实际问题需要或多或少的对Guarded Suspension功能进行扩展(一般是多一个等待队列,任务按照顺序出队处理)。
Guarded Suspension又被称为Guarded Wait 模式、Spin Lock 模式(因为使用了 while 循环去等待),多线程版本if(单线程场景中if语句不需要等待主线程阻塞将没有线程执行了,if判断条件也不会发生变化,而多线程下当前线程的判断结果是有可能被别的线程所篡改的)。
|