同步模式之保护性暂停

news2024/11/25 9:43:14

目录

定义

基本实现

 带超时版 GuardedObject

多任务版 GuardedObject

总结


定义

即 Guarded Suspension,用在一个线程等待另一个线程的执行结果

要点

  • 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
  • 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)
  • JDK 中,join 的实现、Future 的实现,采用的就是此模式
  • 因为要等待另一方的结果,因此归类到同步模式

基本实现

public class GuardedObject{
   private  Object response;
   private  final  Object lock=new Object();
   public Object get(){
       synchronized (lock){
           //条件不满足进行等待
           while (response==null){
               try {
                   lock.wait();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
           return response;
       }
   }

   public void complete(Object response){
       synchronized (lock){
           this.response=response;
           lock.notifyAll();
       }
   }

}
    public static void main(String[] args) {
        ThreadText GuardedObject= new GuardedObject();
        new Thread(()->{
            String response="结果";
            System.out.println("正在加载");
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
            GuardedObject.complete(response);
        }).start();
        System.out.println("wait....");
        //主线程进行等待
        Object o = GuardedObject.get();
        System.out.println("输出结果===》"+o);
    }

 带超时版 GuardedObject

public class GuardedObject {
   private  Object response;
   private  final  Object lock=new Object();
   public Object get(Long millis){
       synchronized (lock){
           //记录最初时间
           long begin=System.currentTimeMillis();
           //已经经历时间
           long timePassed=0;
           //条件不满足进行等待
           while (response==null){
               long waitTime=millis-timePassed;
               if(waitTime<=0){
                   break;
               }
               try {
                   lock.wait();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               timePassed=  System.currentTimeMillis()- begin;
           }
           return response;
       }
   }

   public void complete(Object response){
       synchronized (lock){
           this.response=response;
           lock.notifyAll();
       }
   }

}

测试代码

    public static void main(String[] args) {
        GuardedObject GuardedObject= new GuardedObject();
        new Thread(()->{
            String response="结果";
            System.out.println("正在加载");
            GuardedObject.complete(null);
            try { Thread.sleep(102); } catch (InterruptedException e) { e.printStackTrace(); }
            GuardedObject.complete(null);
            try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); }
            GuardedObject.complete(response);
        }).start();
        System.out.println("wait....");
        //主线程进行等待
        Object o = GuardedObject.get(100);
        System.out.println("输出结果===》"+o);
    
    }

多任务版 GuardedObject

  图中 Futures 就好比居民楼一层的信箱(每个信箱有房间编号),左侧的 t0,t2,t4 就好比等待邮件的居民,右 侧的 t1,t3,t5 就好比邮递员

  如果需要在多个类之间使用 GuardedObject 对象,作为参数传递不是很方便,因此设计一个用来解耦的中间类, 这样不仅能够解耦【结果等待者】和【结果生产者】,还能够同时支持多个任务的管理

新增 id 用来标识 Guarded Object

public class GuardedObject {
    //标识GuardedObject
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    private Object response;

    //获取结果
    public Object get(long timeout) {
        synchronized (this) {
            //开始时间
            long begin = System.currentTimeMillis();
            //经历的时间
            long passedTime = 0;
            while (response == null) {
                long waitTime = timeout - passedTime;
                if (waitTime <= 0) {
                    break;
                }
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //求得经历的时间
                passedTime = System.currentTimeMillis() - begin;
            }
            return response;
        }
    }

    //产生结果
    public void complete(Object response) {
        synchronized (this) {
            //给结果进行赋值
            this.response = response;
            this.notifyAll();
        }
    }

    public GuardedObject(int id) {
        this.id = id;
    }

  
}

中间解耦类

class MailBoxes {
    private static Map<Integer, GuardedObject> boxes = new HashMap<>();
    private static int id = 1;

    //产生唯一id
    private static synchronized int generateId() {
        return id++;
    }

    public static GuardedObject getGuardedObject(int id) {
        return boxes.remove(id);
    }


    public static GuardedObject createGuardedObject() {
        GuardedObject guardedObject = new GuardedObject(generateId());
        boxes.put(guardedObject.getId(), guardedObject);
        return guardedObject;
    }

    public static Set<Integer> getIds(){
        return boxes.keySet();
    }

}

业务相关类

class  People extends  Thread{
    public void run() {
        GuardedObject guardedObject = MailBoxes.createGuardedObject();
        System.out.println("开始收信id==>"+guardedObject.getId());
        Object mail = guardedObject.get(5000);
        System.out.println("收到信id==>"+guardedObject.getId()+" 内容==>"+mail);

    }
}


class Postman extends Thread{
    private  int id;
    private  String mail;
    public Postman(int id,String mail){
        this.id=id;
        this.mail=mail;
    }

    public void run() {
        GuardedObject guardedObject = MailBoxes.getGuardedObject(id);
        System.out.println("送信id==>"+id+" 内容==>"+mail);
        guardedObject.complete(mail);
    }
}

测试代码

  public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new People().start();
            try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
        }
        
        for (Integer id:MailBoxes.getIds()){
            new Postman(id,"内容"+id).start();
          
        }
    }

 测试结果:

开始收信id==>1
开始收信id==>2
开始收信id==>3
送信id==>1 内容==>内容1
送信id==>2 内容==>内容2
送信id==>3 内容==>内容3
收到信id==>1 内容==>内容1
收到信id==>2 内容==>内容2
收到信id==>3 内容==>内容3

总结

保护性暂停(Guarded Suspension)是一种线程间的同步机制,它解决了等待-通知模式中的等待超时和虚假唤醒问题。在保护性暂停模式中,一个线程在等待某个特定条件的满足时,会通过循环的方式不断检查这个条件,同时在条件不满足时通过wait()方法来释放占用的锁,并进入等待状态;当条件被满足时,相应的其他线程会通过notify()或notifyAll()方法来唤醒正在等待的线程。

具体来说,保护性暂停包含以下几个方面:

  1. 条件判断:在保护性暂停中,线程在等待前会先进行一次条件判断,以确定是否需要进入等待状态,从而避免不必要的等待和唤醒。通常情况下,在条件不满足时线程会通过wait()方法进入等待状态,而在条件满足时则继续执行。

  2. 执行顺序:在保护性暂停中,线程之间的执行顺序是不可控的。例如,在一个生产者-消费者模型中,当生产者线程唤醒消费者线程时,不能保证其立即执行,也不能保证消费者线程的执行顺序。

  3. 同步机制:在保护性暂停中,需要使用同步机制来确保线程之间的可见性和互斥性。通常情况下,使用synchronized关键字来保护共享资源,在保证线程之间的可见性和互斥性的同时,避免了死锁和饥饿等问题。

  4. 等待超时:为了避免线程一直等待而导致程序不响应,保护性暂停通常会使用等待超时机制。即在等待一定时间后,如果条件仍然不满足,则主动放弃等待并返回一个默认值,从而避免阻塞线程。

总体来说,保护性暂停是一种有效的线程同步机制,它可以在多线程环境下保证数据的正确性和程序的健壮性。但是,在使用保护性暂停时需要注意线程之间的协作和同步问题,特别是在条件判断和等待超时等方面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/661727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot 实现定时任务动态管理,太爽了

SpringBoot的定时任务的加强工具&#xff0c;实现对SpringBoot原生的定时任务进行动态管理,完全兼容原生Scheduled注解,无需对原本的定时任务进行修改。 快速使用 具体的功能已经封装成SpringBoot-starter即插即用&#xff1a; <dependency><groupId>com.github…

(CVPR-2017)用于目标检测的特征金字塔网络

用于目标检测的特征金字塔网络 论文题目&#xff1a;Feature Pyramid Networks for Object Detection 论文是FAIR发表在CVPR 2017的工作 paper地址 Abstract 特征金字塔是识别系统中用于检测不同尺度对象的基本组件。但最近的深度学习对象检测器避免了金字塔表示&#xff0c;部…

GPT提示词系统学习-第一课-你竟然想不到一个3位数乘法GPT会算错的原因

开篇 在我这个系统的开篇“GPT使我变成超人”中说过,什么样的人使用AI才是起到决定作用的。AI只是工具,它不是万能。使用的人决定了AI可以带什么样的效果。一个很强的人当使用GPT时会形成1+1>2的效果。 因此,提示词的系统化学习是非常重要。这一门课是任何目前国内市面…

使用omp并行技术实现矩阵乘法

矩阵乘法&#xff1a; OpenMP基本概念 OpenMP是一种用于共享内存并行系统的多线程程序设计方案&#xff0c;支持的编程语言包括C、C和Fortran。OpenMP提供了对并行算法的高层抽象描述&#xff0c;特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令&…

Unity基础 视频组件VideoPlayer,视频的播放与控制

在Unity中&#xff0c;视频播放功能具有广泛的应用&#xff0c;以下是一些视频播放在Unity中的常见用途&#xff1a; 游戏引入和过场动画&#xff1a;使用视频播放可以在游戏开始或过场动画中添加引人注目的视频&#xff0c;为游戏制造氛围和引起玩家的兴趣。这种方式可以通过播…

【运维知识进阶篇】zabbix5.0稳定版详解2(自定义监控+报警+图形+模板)

zabbix内容很多&#xff0c;这篇文章继续给大家介绍&#xff0c;zabbix功能很强大&#xff0c;只要是能获取到的数据都可以监控&#xff0c;俗称万物可监控&#xff0c;这也就决定了zabbix有很大的自由度&#xff0c;本篇文章包括自定义监控&#xff0c;自定义报警&#xff0c;…

分类预测 | MATLAB实现PSO-DBN粒子群优化深度置信网络多输入分类预测

分类预测 | MATLAB实现PSO-DBN粒子群优化深度置信网络多输入分类预测 目录 分类预测 | MATLAB实现PSO-DBN粒子群优化深度置信网络多输入分类预测效果一览基本介绍模型描述程序设计参考资料效果一览

LC-1262. 可被三整除的最大和(状态机DP)

1262. 可被三整除的最大和 难度中等229 给你一个整数数组 nums&#xff0c;请你找出并返回能被三整除的元素最大和。 示例 1&#xff1a; 输入&#xff1a;nums [3,6,5,1,8] 输出&#xff1a;18 解释&#xff1a;选出数字 3, 6, 1 和 8&#xff0c;它们的和是 18&#xff…

图的操作算法详解

一.图 基础概念&#xff1a; 有向图 - 图中每个边都有一个方向&#xff0c;例如社交媒体网站上的关注关系图就是有向图。无向图 - 图中每个边都没有方向&#xff0c;例如朋友之间的相互认识关系图可以是无向图。简单图 - 没有自环和重复边的无向图或有向图&#xff0c;例如一…

025.【树形结构算法】

1. 树的定义 树形结构是由n个元素组成的有限集合&#xff0c;如果n0&#xff0c;那么就称为空树&#xff1b;如果n>0&#xff0c;树形结构应该满足以下条件&#xff1a; 有一个特定的结点&#xff0c;称为根结点或根。 除根结点外&#xff0c;其余结点被分成m(m≥0)个互不…

面试官:一个 TCP 连接可以发多少个 HTTP 请求?

目录 &#x1f914; 第一个问题 &#x1f914; 第二个问题 &#x1f914; 第三个问题 &#x1f914; 第四个问题 &#x1f914; 第五个问题 曾经有这么一道经典面试题&#xff1a;从 URL 在浏览器被被输入到页面展现的过程中发生了什么&#xff1f; 相信大多数准备过的同…

产品经理面试常见的25个必问题(一)

1、你认为产品经理的工作职责是什么&#xff1f; ●需求阶段&#xff08;需求收集、需求管理、需求分析、需求评估&#xff09; ●设计阶段&#xff08;业务流程、功能模块、原型交互、需求文档&#xff09; ●开发阶段&#xff08;需求评审、项目管理、测试验收&#xff09…

centos版本的EDA虚拟机搭建1

0、参考博客 Centos镜像国内最全下载地址 VMware Workstation CPU如何设置才更加合理&#xff1f;如何才能发挥虚拟机最大性能 1、下载网站 http://mirrors.aliyun.com/centos/7/isos/x86_64/centos镜像文件下载完成。 2、vmware搭建centos 新建虚拟机。 选择自定义。 …

mysql中的索引

1、索引是什么&#xff1f; 在mysql当中&#xff0c; 内部系统它有两种查询方式&#xff0c; 一种是(全盘扫描查询)&#xff0c;另外一种是通过(索引检索查询)&#xff0c;通过添加了索引的字段进行查询&#xff0c; 可以大大提高查询效率 mysql中的索引相当于一本书中的目录&a…

java 物流配货管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 物流配货管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

centos7系统:HAProxy软件部署

目录 目 的&#xff1a; 硬件需求: ​编辑 实验环境配置&#xff1a; haproxy的服务器配置&#xff1a; nfsrps服务器部署&#xff1a; nginx服务器1部署: nginx服务器2部署&#xff1a; 目 的&#xff1a; 两台nginx服务器做web服务&#xff0c;haproxy服务器做调度负载均…

(6.9-6.15)【大数据新闻速递】

【上海数交所将携手清华大学等举办首届数据资产入表研修班】 上海数据交易所获悉&#xff0c;数交所将联合清华大学五道口金融学院、上海市数商协会于6月28日至29日举办首届数据资产入表研修班。财政部印发《企业数据资源相关会计处理暂行规定&#xff08;征求意见稿&#xff…

前沿应用丨大规模无人机集群与“虚实结合”半实物仿真系统

一、应用背景 无人机集群在军事、安全、救援、航空监测、物流配送等领域具有广泛的应用前景。它可以提高任务执行的效率、灵活性和安全性&#xff0c;同时降低人力资源的需求和风险&#xff0c;无人机集群研究涉及多个学科领域&#xff0c;如机器人学、控制理论、通信技术和人工…

【算法与数据结构】383、LeetCode赎金信

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题的思路和242、有效的字母异位词的思路一样   程序如下&#xff1a; class Solution { public…

好好存钱,是成年人最顶级的自律

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 王尔德说&#xff1a;“在我年轻的时候&#xff0c;曾以为金钱是世界上最重要的东西。现在我老了&#xff0c;才知道的确如此。” 路遥说&#xff1a;“钱是好东西&#xff0c;它能使人不再心慌&#…