什么是Guarded Suspension Pattern?

设想一个场景,你在家里换衣服,突然门铃响了,总不能换到一半出去开门吧,于是说:“请稍等”。换完衣服再把房门打开。

当现在不适合马上执行某一个操作的时候,就需要这个想要执行操作的线程进行等待。

这里我们用代码来说明一切:

我们模拟4个人存钱取钱的场景,银行初始金额为0。

package guardedSuspension;public class Bank {private int money = 0;public Bank(){}public synchronized void withDraw(int money){while(this.money-money<0){try {wait();//只要钱不够 就不能进入临界区} catch (InterruptedException e) {e.printStackTrace();}}//开始取钱this.money-=money;System.out.println(Thread.currentThread().getName()+"取钱"+money+",还剩"+this.money);notifyAll();//唤醒所有线程}public synchronized void save(int money){this.money+=money;//存钱System.out.println(Thread.currentThread().getName()+"存了钱"+money+",现在银行还剩"+this.money+"元");}
}

然后是实现了Runnable的target:

package guardedSuspension;import java.util.Random;public class PersonRunnable implements Runnable {private Bank bank;PersonRunnable(Bank bank){this.bank = bank;}@Overridepublic void run() {Random random = new Random();int money = random.nextInt(10);//0-9随机数bank.save(money);//存钱int money2 = random.nextInt(10);//0-9随机数bank.withDraw(money2);//取钱}}

最后写一个测试类:

package guardedSuspension;public class Test {public static void main(String[] args) {Bank bank = new Bank();PersonRunnable t1 = new PersonRunnable(bank);new Thread(t1,"Diana").start();new Thread(t1,"Tommy").start();new Thread(t1,"Ginna").start();new Thread(t1,"Jerry").start();}
}

下面是一种运行结果:

现在我们开始来看代码,对于withDraw方法,存在着一个“警戒条件”,也就是只有取钱完money仍然大于0才能执行。

当线程抵达代码段while(this.money-money>0)时,会分成满足警戒条件和不满足警戒条件两种情况,警戒条件(this.money-money>=0)成立时,代码不会进入while块,而是直接进入下一个语句,直接取钱,而不会wait,警戒条件不成立,才会执行wait。

执行wait后线程等着被notify/notifyAll,然而更根本的时,线程在等待警戒条件的成立,等到收到notify/notifyAll时再判断警戒条件成立不成立,如果成立就取钱,否则继续进入wait set。这就是为什么有时候(比如上方的运行结果)程序迟迟不会结束的原因,因为所有人都存钱完了,然后还是不够取,所以那个没有足够钱取的线程就一直呆在wait set了。

整理一下,关于警戒条件的架构使用方法是:

while("警戒条件"的逻辑否定){使用wait等待
}
进行"目的操作"

该模式的时序图如下:

如何理解Guarded Suspension Pattern?

1、有条件的synchronized,在Single Threaded Execution的基础上,只要有一个线程进入临界区间,其他线程就不能进入,而是等待。因此可以称为有条件的synchronized。

2、多线程版的if。多个线程不符合警戒条件就不执行,否则就执行。

忘记更改状态和生命性

wait中的线程会在被notify/notifyAll的时候重新测试警戒条件,如果始终达到不了警戒条件则依然会进入wait set。

如果忘了修改GuardedObject参与者(比如上面的money)的状态,会导致警戒条件永远无法成立,使得线程无法继续前进,使得程序失去生命性。

各种实现方法

1、guarded wait,就像本例的实现,使用wait等待,直到被notify/notifyAll后再次测试警戒条件。使用wait等待的时间,其实就是停止在等待区里停止执行,所以不会浪费Java执行环境的处理时间:

//等待端的范例
while(!ready){wait();
}//唤醒端的范例
ready = true;
notifyAll();

2、busy wait(忙等待),线程不使用wait方法等待,而是使用yield方法(把当前运行机会交给优先级高的线程),然后不断测试条件的实现方法。因此等待中的线程还是运行这,会浪费jvm的时间。yield是Thread的类方法,这个方法不会解除锁,所以这个方法不应该写在synchronized里,否则容易死锁。yield只是放弃当前cpu的使用,让给其他线程,当前线程置为可运行状态。也就是说虽然当前线程调用了yield,还是可能接下来是自己运行,正确示例:

//等待端的范例
while(!ready){Thread.yield();
}
//唤醒端的范例
ready = true;
//没有notify/notifyAll

3、spin lock(自旋锁)。旋转而锁定的意思,表现出条件成立前while循环不断旋转的样子。spin lock有时候意思和guarded wait相同,有时候和guarded wait相同。有时候一开始是busy wait,之后换成guarded wait的方式。另外,有些以硬件实现的同步机制,也称为spin lock。

4、polling(进行调查)。反复检查某个事件是否发生,当发生时,就进行对应处理的方式。

Guarded Suspension Pattern相关推荐

  1. (Guarded Suspension Design Pattern)

    多线程设计模式之保护性暂停模式 定义 保护性暂停模式(Guarded Suspension Design Pattern):当线程在访问某个对象时,发现条件不满足时,就暂时挂起等待条件满足时再次访问. ...

  2. 实战并发编程 - 08基于Guarded Suspension模式优化轮询while(true)

    文章目录 Guarded Suspension模式简介 看牙医的就诊流程 代码举例 总结与拓展 Guarded Suspension模式简介 guarded在这里是"保护"的意思: ...

  3. Java并发编程实战~Guarded Suspension模式

    Guarded Suspension 模式 比如,项目组团建要外出聚餐,我们提前预订了一个包间,然后兴冲冲地奔过去,到那儿后大堂经理看了一眼包间,发现服务员正在收拾,就会告诉我们:"您预订的 ...

  4. Java高并发编程详解系列-Guarded Suspension设计模式

    导语   什么是Guarded Suspension模式,Suspension 意思是挂起,暂停的.而Guarded则表示担保的意思,连起来的就是确保挂起.也就是说当线程访问某个对象的时候,发现条件不 ...

  5. 并发设计模式之Guarded Suspension模式

    - 原文链接: http://www.joyhwong.com/2016/11/19/并发设计模式之guarded-suspension模式/ Guarded Suspension意为保护暂停,其核心 ...

  6. 并发设计模式——保护性暂停(Guarded Suspension)

    并发设计模式--保护性暂停(Guarded Suspension) 什么叫做 Guarded Suspension ? guarded 的意思是"守护.担保",suspension ...

  7. java暂挂状态,Guarded Suspension(保护性暂挂)模式

    思维导图 思维导图 Guarded Suspension 模式简介 Guarded Suspension 模式的核心是一个受保护方法(Guarded Method).该方法在执行其所需要真正执行的操作 ...

  8. 多线程模式(2):Guarded Suspension模式

    为什么80%的码农都做不了架构师?>>>    封装请求类 package com.xqi.g_s;import com.xqi.f.Data;/*** 请求封装* * @autho ...

  9. 实战并发编程 - 09多线程Guarded Suspension模式案例实战

    文章目录 需求 Code (上) [1. init初始化报警服务] [2.onConnected方法建立连接] [3.HeartbeatTask心跳检查] [4.tesConnection测试是否连接 ...

  10. Java多线程设计模式(4)线程池模式

    前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将"委托消息的一端"和"执行消息的一端&qu ...

最新文章

  1. 一打在2019年亮相的迷人科技项目:飞行汽车、子弹头列车、登月、……
  2. 装饰器前奏2(2017年8月23日 11:50:39)(2017年8月29日 16:07:32)
  3. AFNetworking 3.0 源码解读(十)之 UIActivityIndicatorView/UIRefreshControl/UIImageView + AFNetworking...
  4. 一文带你马上清楚bootstrap的栅格系统
  5. SuperSocket与Netty之实现protobuf协议,包括服务端和客户端
  6. P2842-LJJ算数【数论,快速幂】
  7. LeetCode 791. 自定义字符串排序(map)
  8. Redis分布式锁的概念
  9. 灵感库 | 让设计师欲罢不能的设计网站
  10. JavaScript中的事件循环
  11. 基于遗传算法优化BP神经网络预测和分类MATLAB实现-附代码
  12. python语法简洁清晰、特色之一是强制用作为语句缩进_问道python之基础篇【一】 认识python...
  13. 一文了解SG2525AN
  14. 华为全联接大会2022丨华为云打造可信认证体系,加速开发者成长
  15. 【计算机视觉】Lecture 28:跟踪简介
  16. [Django项目案例]搭建用户与商品后台管理系统
  17. python学习笔记分享(四十)网络爬虫(7)反爬虫问题,解决中文乱码,登陆和验证码处理
  18. MySQL—自定义函数
  19. PTA 6-6 使用函数计算两个复数之积
  20. 代码真的可以体现一个人的智商吗?

热门文章

  1. 微信html5活动页面制作,完整的微信H5活动页面设计规范
  2. 第五次课堂总结——付胤
  3. 经典算法:遗传算法(GA)
  4. 腾讯、淘宝的架构大数据你有了解么?大数据技术及算法为你解析
  5. 怎么以最新汇率牌价计算XX美元相当于多少人民币
  6. 美元用计算机怎么算,美金人民币汇率换算(人民币兑换率计算器)
  7. B. Diverse Garland
  8. HALCON灰度值变换
  9. SpringSecurity前后端分离02(授权)
  10. mysql rpl_MySQL半同步复制rpl_semi_sync_master_timeout测试