Semaphore (信号量)是由计算机科学家Dijkstra在1965年提出的,广泛应用不同的操作系统,在管程提出之前信号量就是并发编程领域的霸主!几乎所有并发的语言都支持信号量机制。

Semaphore 也有被翻译成信号灯,因为其机制就像我们日常生活中的红绿灯,车辆的通行看红绿灯,对应编程世界的线程能不能执行得看信号灯!

Semaphore 用来多线程互斥问题,相对于synchronized和Lock来说它允许多个线程访问一个临界区!例如各种池:数据库连接池、对象池等,这些池的需求就是同一时刻允许多个线程同时使用连接池。

Semaphore的模型可以概括为一个计数器、一个等待队列、三个方法。 三个方法原子性分别是init()、down()、up()

init():设置计数器的初始值。

down():将计数器的值减一,如果减了一之后,计数器的值小于0,则当前的线程被阻塞,否则继续执行。

up():将计数器的值加一,如果加了一之后,计数器的值小于等于0,则唤醒等待队列中的一个线程,并且将它移除出等待队列。(注意是小于等于0,不应该理解为大于等于0,因为大于等于0表明此时没有等待的线程,所以不会有唤醒这个操作。)

简单的理解就是 Semaphore 就是通过这三个方法来改变计数器,通过计数器的值来判断此时的线程是应该加入到等待队列中等待还是成功执行。

信号量模型也被称为PV原语,也就是downup操作最早称为P操作和V操作,有些人还称为semWaitsemSignal在JAVA中信号量模型是由 java.util.concurrent.Semaphore 的实现,并且downup对应的实现方法是acquire和release,我们来看下简单的使用例子

    int count;final Semaphore semaphore   = new Semaphore(1); // 初始化信号量// 用信号量保证互斥    void addOne() {try {semaphore.acquire();   //对应downcount+=1;} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();  //对应up}}复制代码

如果你想多让几个线程进去临界区,那么就把Semaphore构造器中的1改为你想要的线程数。

可以理解为颁发许可证,比如想同时允许3个线程进入临界区,构造器中的数就填3,理解为搞了3张许可证,然后颁发出去,谁拿到了许可证谁就能进临界区,进入临界区后的线程搞完事了,就归还许可证,然后出去。

Semaphore的内部共存在Sync、NonfairSync、FairSync三个类,NonfairSyncFairSync类继承自Sync类,Sync类继承自AbstractQueuedSynchronizer抽象类,也就Semaphore是依托于NonfairSync、FairSync来实现的。

      public Semaphore(int permits) {sync = new NonfairSync(permits);}public Semaphore(int permits, boolean fair) {sync = fair ? new FairSync(permits) : new NonfairSync(permits);}
复制代码

可以通过构造函数来指定为公平锁还是非公平锁,公平的意思这个许可只会给按先来后到的顺序给等待队列中的线程。而非公平的意思就是对于任何申请许可的线程,都第一时间看是否有多余的许可,如果有则给此线程。

        protected int tryAcquireShared(int acquires) {   //公平for (;;) {if (hasQueuedPredecessors())return -1;int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires);   //非公平}final int nonfairTryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining)return remaining;}}
复制代码

差别就在于有没hasQueuedPredecessors(),这个方法就是判断当前线程是否是等待队列中的头结点,如果不是,则不给于分配。 大致Semaphore的模型和模型实现思路就是这样,建议多看看源码,不难的可以加深理解,并且懂得具体实现之后能掌握把控更多细节,还不怕面试官问。


如有错误欢迎指正!

个人公众号:yes的练级攻略

有相关面试进阶(分布式、性能调优、经典书籍pdf)资料等待领取

面试官:说说Java中的信号量?Semaphore相关推荐

  1. 【性能优化】面试官:Java中的对象和数组都是在堆上分配的吗?

    写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...

  2. 面试官:Java中 serialVersionUID 的作用是什么?举个例子说明

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料!来源:blog.csdn.net/andy_zhang200 ...

  3. 面试官:Java中线程是按什么顺序执行的?

    本文分享自华为云社区<[高并发系列]Java中线程到底是按什么顺序执行的?你了解的可能是错误的!>,原文作者:冰 河 . Java中线程的执行顺序可能与你想的不一样!一文解密多线程的执行顺 ...

  4. java 委托_面试官:java双亲委派机制及作用

    什么是双亲委派机制 当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类. 类加载器的类别 Bootst ...

  5. 【Redis系列】面试官:Redis中的数据已经过期,为什么还占用这内存?

    如果有面试官问Redis中的数据已经过期为什么还占用这内存? 它是因为Redis本身的过期策略和缓存淘汰机制所导致的. 说说Redis的过期策略和缓存淘汰机制 先来说说Redis的过期策略,Redis ...

  6. 面试官:Vue中组件和插件有什么区别?

    一.组件是什么 回顾一下对组件的定义: 组件就是把图形.非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,在Vue中每一个.vue文件都可以视为一个组件 组件的优势 降低整个系统的耦合度 ...

  7. 面试官:Redis中集合数据类型的内部实现方式是什么?

    虽然已经是阳春三月,但骑着共享单车骑了这么远,还有有点冷的.我搓了搓的被冻的麻木的手,对着前台的小姐姐说:"您好,我是来面试的."小姐姐问:"您好,您叫什么名字?&quo ...

  8. java semaphore(0)_面试官:说说Java中的信号量?Semaphore

    Semaphore (信号量)是由计算机科学家Dijkstra在1965年提出的,广泛应用不同的操作系统,在管程提出之前信号量就是并发编程领域的霸主!几乎所有并发的语言都支持信号量机制. Semaph ...

  9. java中double类型占几个字节_面试官:Java 中有几种基本数据类型是什么?各自占用多少字节?...

    认识基本数据类型 在学习基本数据类型之前,我们先认识一下这两个单词:1.bit --位:位是计算机中存储数据的最小单位,指二进制数中的一个位数,其值为"0"或"1&quo ...

最新文章

  1. 100万人同时抢1万张火车票,极限并发带来的思考
  2. vs 输入代码时出现火花_在Visual Basic的立即窗口内输入以下语句 X=65
  3. HttpSessionListener监听Session的创建和失效
  4. 基于Linux的socket编程模板
  5. Perl中use、require的用法和区别
  6. RHEL5.4 iptables 配置详解(图)
  7. Java基础--String类底层实现原理及API示例详解
  8. 新技术层出不穷,一入前端深似海!
  9. cgi硬盘安装器_系统镜像安装CGI备份还原
  10. DevOps on DevCloud|如何构建Kotlin开发的Android Apps
  11. EXCEL同一个界面下打开两个表格比较
  12. VS注释和取消注释快捷键自定义
  13. Win10驱动签名总结
  14. 老徐WEB:js入门学习 - javascript函数和闭包
  15. 1. SpringBoot 整合 Canal
  16. PTA(二十五) 算法设计与分析 第七章 贪心法 7-1 装箱问题 (20 point(s))
  17. 传感器与检测技术基础知识(5)—— 电容式传感器
  18. python编写投票统计结果
  19. pdf裁边app_PDF切边裁剪(paper for kindle)
  20. 考勤数据计算-Excel

热门文章

  1. ALDownloadManager 基于Alamofire封装的下载器
  2. 计算两个日期之间的工作日
  3. nginx配置websocket代理
  4. Spring Boot中使用JavaMailSender发送邮件
  5. 开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器
  6. RAID-5 恢复技术
  7. 远程桌面关闭重启电脑的方法
  8. mysql 类型转换 cast 将 float 转换为 decimal
  9. 如何创建从ArcIMS到ArcSDE/Oracle的直接连接?
  10. ReentrantReadWriteLock读写锁及其在 RxCache 中的使用