信号量 Semaphore 的四个核心面试问题

今天所有的混乱与芜杂,努力与精进,都将在进步中变得更加清晰。

——新京报

  • Semaphor面试频率
  • 发起视频面试。。。

Q:了解Semaphore吗,讲讲?

> 那必须深入的理解了的呀。

中文信号量,用于计数。从概念上讲,信号量维护一组许可证(permit)。

acquire

从该信号量获取一个许可,阻塞直到获得了一个许可或线程被中断。
如果有许可证可用,则获取许可证并立即返回,从而将可用的许可证的数量减一。

如果无可用许可,则出于线程调度的目的,当前线程将被禁用,并处于休眠状态,直到发生以下两种情况之一:

  • 其他某线程为此信号量调用release方法,接下来将为当前线程分配一个许可
  • 其他某线程中断当前线程

如果当前线程:

  • 在进入此方法时已设置其中断状态,或者
  • 在等待许可证时被打断

那么就会抛InterruptedException,并清除当前线程的中断状态。

tryAcquire

无超时设置的tryAcquire方法不遵循公平性设置,而是会取得任何可用的许可。不会阻塞,但有可设置等待时间的版本。
仅在调用时有一个许可可用时,才从此信号量获取。

  • 如果有许可证,则获取许可证,立即返回true,将可用的许可数量减一
  • 如果没有可用的许可,则此方法将立即返回false

即使将此信号量设置为公平策略,如果有可用的调用tryAcquire也会立即获得许可,无论当前是否正在等待其他线程。虽然破坏了公平性,这种插队的行为在某些情况下还是有用的。如果非要遵守公平性,请使用几乎等效的 tryAcquire(0, TimeUnit.SECONDS)(它还会检测中断)

nonfairTryAcquireShared

release

每个release()添加一个许可,有可能释放阻塞获取者。
释放许可证,将其返回给信号量,可用许可证数量加一。如果有任何线程试图获取许可,则选择一个线程并授予刚刚释放的许可。该线程是出于线程调度目的而被 (重新)启用。

并不要求释放许可证的线程必须已经通过调用acquire()获得了该许可证。通过在应用程序中编程约定,可以正确使用信号量。

  • 不出所料,该同步器的内部抽象类 Sync 也是继承了AQS,该方法内部也是实现调用的 AQS 框架接口中已约定好的的共享模式的释放锁资源。

上图蓝框内的即由AQS 的同步器子类来根据自己的需要实现:

tryReleaseShared

当然了此类还提供方便的方法来一次获取和释放多个许可证。
不过,当在不公平的情况下使用这些方法时,请注意无限期推迟的风险增加。

内存一致性影响

在调用一个释放方法,例如release() 先行发生(happens before)于在另一个线程中成功执行的获取方法,例如acquire()

> 结合该机制也就保证了该类是线程安全的。

Q:该类一般怎么使用,写个例子?

最佳实践

此类并没有使用实际的什么许可证对象。信号量只是保持可用数量的计数并采取相应措施。
与无法访问某些(物理或逻辑)资源相比,信号量通常用于限制线程数。

使用信号量控制对项目池的访问的类:

class Pool

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java源码模拟面试解析指南 文章被收录于专栏

<p> “挨踢”业行情日益严峻,企业招聘门槛愈来愈高,大厂hc更是少之又少,而Java技术面试普遍对基础知识的掌握考察特别深,大多数同学突击所看的 Java 面试基础知识点根本达不到面试官近乎挑剔的要求。 本专刊针对如今的校招及社招痛点,深入解析 JDK 的核心源码,探究 JDK 的设计精髓及最佳实践,同时以模拟面试的场景切入,让同学们在阅读过程中也能轻松掌握面试技巧。 本专刊购买后即可解锁所有章节,故不可以退换哦~ </p>

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 11:30
点赞 评论 收藏
分享
机械打工仔:我来告诉你原因,是因为sobb有在线简历,有些HR为了快会直接先看在线简历,初步感觉不合适就不会找你要详细的了
投了多少份简历才上岸
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务