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