Java中Semaphore(信号量)的使用

2023-05-16

Semaphore的作用:

在java中,使用了synchronized关键字和Lock锁实现了资源的并发访问控制,在同一时间只允许唯一了线程进入临界区访问资源(读锁除外),这样子控制的主要目的是为了解决多个线程并发同一资源造成的数据不一致的问题。在另外一种场景下,一个资源有多个副本可供同时使用,比如打印机房有多个打印机、厕所有多个坑可供同时使用,这种情况下,Java提供了另外的并发访问控制--资源的多副本的并发访问控制,今天学习的信号量Semaphore即是其中的一种。

Semaphore实现原理初探:

Semaphore是用来保护一个或者多个共享资源的访问,Semaphore内部维护了一个计数器,其值为可以访问的共享资源的个数。一个线程要访问共享资源,先获得信号量,如果信号量的计数器值大于1,意味着有共享资源可以访问,则使其计数器值减去1,再访问共享资源。

如果计数器值为0,线程进入休眠。当某个线程使用完共享资源后,释放信号量,并将信号量内部的计数器加1,之前进入休眠的线程将被唤醒并再次试图获得信号量。

就好比一个厕所管理员,站在门口,只有厕所有空位,就开门允许与空侧数量等量的人进入厕所。多个人进入厕所后,相当于N个人来分配使用N个空位。为避免多个人来同时竞争同一个侧卫,在内部仍然使用锁来控制资源的同步访问。

Semaphore的使用:

Semaphore使用时需要先构建一个参数来指定共享资源的数量,Semaphore构造完成后即是获取Semaphore、共享资源使用完毕后释放Semaphore。

Semaphore semaphore = new Semaphore(10,true);
semaphore.acquire();
//do something here
semaphore.release();

下面的代码就是模拟控制商场厕所的并发使用:

public class ResourceManage {
    private final Semaphore semaphore ;
    private boolean resourceArray[];
    private final ReentrantLock lock;
    public ResourceManage() {
        this.resourceArray = new boolean[10];//存放厕所状态
        this.semaphore = new Semaphore(10,true);//控制10个共享资源的使用,使用先进先出的公平模式进行共享;公平模式的信号量,先来的先获得信号量
        this.lock = new ReentrantLock(true);//公平模式的锁,先来的先选
        for(int i=0 ;i<10; i++){
            resourceArray[i] = true;//初始化为资源可用的情况
        }
    }
    public void useResource(int userId){
        try{
            semaphore.acquire();
            int id = getResourceId();//占到一个坑
            System.out.print("userId:"+userId+"正在使用资源,资源id:"+id+"\n");
            Thread.sleep(100);//do something,相当于于使用资源
            resourceArray[id] = true;//退出这个坑
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            semaphore.release();//释放信号量,计数器加1
        }
    }
    private int getResourceId(){
        int id = -1;
        try {
            lock.lock();//虽然使用了锁控制同步,但由于只是简单的一个数组遍历,效率还是很高的,所以基本不影响性能。
            for(int i=0; i<10; i++){
                if(resourceArray[i]){
                    resourceArray[i] = false;
                    id = i;
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return id;
    }
}
public class ResourceUser implements Runnable{
    private ResourceManage resourceManage;
    private int userId;
    public ResourceUser(ResourceManage resourceManage, int userId) {
        this.resourceManage = resourceManage;
        this.userId = userId;
    }
    public void run(){
        System.out.print("userId:"+userId+"准备使用资源...\n");
        resourceManage.useResource(userId);
        System.out.print("userId:"+userId+"使用资源完毕...\n");
    }

    public static void main(String[] args){
        ResourceManage resourceManage = new ResourceManage();
        Thread[] threads = new Thread[100];
        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(new ResourceUser(resourceManage,i));//创建多个资源使用者
            threads[i] = thread;
        }
        for(int i = 0; i < 100; i++){
            Thread thread = threads[i];
            try {
                thread.start();//启动线程
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

最后,Semaphore除了控制资源的多个副本的并发访问控制,也可以使用二进制信号量来实现类似synchronized关键字和Lock锁的并发访问控制功能。

转载于:https://www.cnblogs.com/cl1024cl/p/6205011.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中Semaphore(信号量)的使用 的相关文章

  • Java中String的字符编码是什么?

    我实际上对 Java 中字符串的编码感到困惑 我有一些问题 如果您知道答案 请帮助我 1 Java字符串在内存中的本机编码是什么 当我写作时String a Hello 将以哪种格式存储 由于 Java 是独立于机器的 我认为系统不会进行编
  • 如何用泛型返回类型推断方法的具体返回类型?

    给出以下接口 interface Random extends java util function Supplier
  • 使用矩阵参数创建 GET 请求

    我将使用的网络服务需要矩阵参数 http tester com v1 customers lastname Jackson firstname Tim bookingreference 7Y9UIY 而不是通常的 http tester c
  • 如何设置评分栏的星星颜色?

    如何设置评分栏的星星颜色 我想要黄色星星 最简单的方法 android progressTint color color 光滑有光泽
  • Java 中修剪字符串的可能前缀

    I have String str 我想从中提取不包括可能的前缀的子字符串 abc 我想到的第一个解决方案是 if str startsWith abc return str substring abc length return str
  • emacs 的最佳 java 工具 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 我的代码中出现 ArrayIndexOutOfBoundsException 的原因是什么?

    我正在 Java 中实现凸包的格雷厄姆扫描算法 我在运行代码时收到此错误 对于输入字符串 10 18 Exception in thread main java lang ArrayIndexOutOfBoundsException 0 a
  • C# 到 Java:Base64String、MemoryStream、GZipStream

    我有一个在 NET 中压缩的 Base64 字符串 我想将其转换回 Java 中的字符串 我正在寻找一些与 C 语法等效的 Java 语法 特别是 Convert FromBase64String 内存流 压缩流 这是我想要转换的方法 pu
  • Checkstyle 规则防止调用某些方法和构造函数

    是否可以使用 Checkstyle 来禁止使用某些使用系统相关默认值 区域设置 字符集等 的构造函数或方法 我更喜欢强制执行一项政策 程序员应该明确了解系统相关的值 所以我认为以下物品是危险的 all the constructors of
  • Swing 是否支持 Windows 7 风格的文件选择器?

    我刚刚添加了一个标准 打开文件 与我正在编写的一个小型桌面应用程序的对话 基于JFileChooserSwing 教程的入口 http download oracle com javase tutorial uiswing componen
  • Android 是否可以获取用户和设备所在国家/地区的货币代码?

    是否可以获取用户和设备所在国家 地区的货币代码 我想将用户当前国家 地区的国家 地区代码设置为默认国家 地区 我们在 Android 中有解决方案吗 由于这段代码可能对您有帮助 public class CurrencyTest publi
  • 如果Jetty的密钥库中有多个证书,它如何选择?

    我们的系统中有一些代码用于自动将自签名证书生成到密钥库中 然后由 Jetty 使用 如果给定主机的密钥已经存在 那么什么也不会发生 但如果它不存在 我们会生成一个新密钥 如下所示 public void generateKey String
  • 导入数据期间解析日期格式的最佳方法

    我创建了在数据导入 400 K 记录 期间解析视图不同日期格式的方法 我的方法捕获 ParseException 并尝试在不同时使用下一种格式解析日期 问题 在数据导入期间设置正确的日期格式是更好的方法 更快 吗 private stati
  • 在 Android 谷歌地图中绘制 4K 折线

    我现在正在开发一个适用于 Android 设备的应用程序 主要功能是在地图上绘制折线以显示城市中每条街道的交通情况 不幸的是 当我绘制大约 3K 折线时 数量会根据屏幕尺寸和缩放级别而减少 我的地图变得非常慢 我没有提及绘制所有线条的时间
  • Java TreeMap时间复杂度-lowerKey

    时间复杂度是多少lowerKey Java实现中的操作TreeMap 我认为它是 log n 但我在文档中找不到它 更基本操作的复杂性已有详细记录 此实现提供了有保证的 log n 时间成本 containsKey 获取 放置和删除操作 顺
  • 如何从java程序中编译.java文件[重复]

    这个问题在这里已经有答案了 可能的重复 从 Java 内部编译外部 java 文件 https stackoverflow com questions 10889186 compiling external java files from
  • OutputStream 到 DB2 数据库表的 BLOB 列

    在 DB2 数据库中 我有下表 CREATE TABLE MyTestTable MYPATH VARCHAR 512 NOT NULL MYDATA BLOB CONSTRAINT MYTESTTABLE PK PRIMARY KEY M
  • Spring Data 中 IQueryable 的等效项

    我习惯了 Net 和 LINQtoEntities 尤其是 IQueryable 部分 它允许在获取结果之前通过不同的函数传送请求 Spring数据中是否存在类似的东西 或者任何其他 java ORM 我希望能够做的基本示例 private
  • struts2中如何访问url参数

    我正在做一个struts2项目 我在项目中创建了 url 并使用标签传递了参数 我的问题是如何读取操作中的参数 另外 如果执行相同的操作 我将能够将参数视为查询字符串 我问是因为我无法做到 而且我在其中一个教程中看到了它 通常 您将通过使用
  • 从 Web 服务器异步调用应用程序

    我有一个用 Spring 制作的 在 Tomcat 上运行的 Web 应用程序 在同一台机器上有一个普通的 Java 应用程序 我想通过从Web服务器调用Java应用程序来执行它 但我想让应用程序不会使用服务器的资源 它涉及分类器的训练 因

随机推荐

  • 获取百度地图POI数据一(详解百度返回的POI数据)

    POI是一切可以抽象为空间点的现实世界的实体 xff0c 比如餐馆 xff0c 酒店 xff0c 车站 xff0c 停车场等 POI数据具有空间坐标和各种属性 xff0c 是各种地图查询软件的基础数据之一 百度地图作为国内顶尖的地图企业 x
  • c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度

    linux epoll系列3 利用epoll wait设置timeout时间长度 epoll wait函数的第四个参数可以设置 xff0c epoll wait函数的等待时间 xff08 timeout时间长度 xff09 例子1 xff0
  • socket编程原理

    socket编程原理 1 问题的引入 1 普通的I O操作过程 UNIX系统的I O命令集 xff0c 是从Maltics和早期系统中的命令演变出来的 xff0c 其模式为打开一读 写一关闭 xff08 open write read cl
  • linux考试题答案2016,2016年4月全国自主考试(网络操作系统)真题

    2016年4月全国自主考试 网络操作系统 真题及答案解析 2016年4月全国自主考试 网络操作系统 真题及答案 xff0c 计算机网络自主考试历年真题 一 单项选择题 本大题共20小题 xff0c 每小题2分 xff0c 共40分 在每小题
  • (14)嵌入式软件开发工程师技能要求总结

    找准一个行业方向 xff1a 音视频 人工智能 深度学习 视觉识别 机器学习 嵌入式软件开发工程师 xff1a 技能要求 xff1a 熟悉 Linux操作系统 shell 脚本语言 mysql 的开发 xff0c 部署 xff0c 优化优先
  • 原来bug解决了,是这样的感觉

    终于过了 xff0c 感觉好想哭啊 xff0c 又莫名其妙的爽 xff0c 原来这就是bug 转载于 https www cnblogs com allison aichipingguo p 10018117 html
  • 闲话handle和handler

    虽然handle和handler只有一个字符之差 xff0c 但在计算机的世界里 xff0c 含义却大相径庭 1 先说说handle 北京话说 34 一边儿玩儿去 xff0c 玩勺子把儿去 34 xff0c 34 勺子把儿 34 说的就是h
  • 大数据发展前沿 期末总结复习

    其实就是简单的在网上搜了一下每个重要词条的基本概念 1 对抗学习 xff08 含Pytorch最简单的深度学习命令 xff09 生成对抗网络 xff08 GAN xff09 是非监督式学习的一种方法 xff0c 透过两个神经网络相互博弈的方
  • 出租车Jt/T 905协议与部标1078协议融合的网约车视频监控平台

    出租车 jt t 905协议 xff0c 是 jt t 808 协议的一个变种 xff0c 设计者将部标 808 协议拿过来 xff0c 并不是单纯的增加网约车相关的指令集 xff0c 而且对原有的指令如定位 0 0200 指令也进行了修改
  • 几款Git GUI客户端工具

    工欲善其事 xff0c 必先利其器 作为一名开发人员 xff0c 你不可能不知道git xff0c 无论你是开发自己的开源项目还是和团队一起进行大规模产品的开发 xff0c git都已经是源代码管理工具的首选 当然 xff0c 那些hard
  • 毕设(一)C#的百度api调用

    这个学期就要毕业了 xff0c 选了一个无人机地面站软件设计的题目 xff0c 这几天也开始着手做 xff0c 首先做了一个百度地图的调用 xff0c 这里因为是上位机的开发 xff0c 所有就不介绍Javascript的 调用方法 xff
  • tf-ros

    http wiki ros org cn tf Tutorials https www ncnynl com archives 201708 1881 html 1 广播变换 发布坐标之间的坐标关系 include lt ros ros h
  • Makefile shell subst $(1)

    MAKE 3 80 realpath 61 shell top srcdir scripts realpath sh 39 subst SQUOTE SQUOTE 1 39 以上Makefile思考好几天不得要领 xff1a 今天想通了 x
  • docker 卸载

    使用yum安装docker xff08 安装过程可以参照linux 安装docker xff09 xff0c 如需卸载docker可以按一下步骤操作 xff1a 1 查看当前docker状态 如果是运行状态则停掉 systemctl sto
  • VIN-Fusion config with Realsense D435i

    First shot Copy the launch file in package VINS Fusion to the directory of realsense2 cameara launch cp home william cat
  • 算法的5个层次

    对算法的掌握 xff0c 大致可以分为5个层次 听说 了解 理解 实现 应用 Level 1 xff1a 听说 知道算法名 知道算法功能 Leven 2 xff1a 了解 知道算法原理 自然语言描述 知道算法优缺点 Leven 3 xff1
  • elf文件下载出错问题

    现在遇到的是sof文件下载有问题 xff0c 不是对应的sof文件 在复制工程后 xff0c 可以在assignment gt setting中指定生成文件所在的文件夹 xff0c 防止sof文件的不对应 转载于 https www cnb
  • 搞定INTEL快速存储技术(用SSD硬盘做缓存加速)

    给朋友买了个联想 ideapad s400 超级本 xff0c 还真是锻炼我的 idea 啊 xff0c 原机不带 WIN7 系统 xff0c 所以只好自己动手装 WIN7 xff0c 并打开 24G SSD 硬盘做缓存 一 用常规方法 G
  • php取今天开始结束,PHP获取今天开始和结束的时间戳

    PHP获取今天开始和结束的时间戳 xff1a t 61 time 开始时间戳 start 61 mktime 0 0 0 date 34 m 34 t date 34 d 34 t date 34 Y 34 t 结束时间戳 end 61 m
  • Java中Semaphore(信号量)的使用

    Semaphore的作用 xff1a 在java中 xff0c 使用了synchronized关键字和Lock锁实现了资源的并发访问控制 xff0c 在同一时间只允许唯一了线程进入临界区访问资源 读锁除外 xff0c 这样子控制的主要目的是