Semaphore实现为一种基于计数的信号量,Semaphore管理着一组虚拟的许可集合,这种许可 可以作为某种凭证,来管理资源,在一些资源有限的场景下很有实用性,比如数据库连接,应 用可初始化一组数据库连接,然后通过使用Semaphore来管理获取连接的许可,任何线程想要 获得一个连接必须首先获得一个许可,然后再凭这个许可获得一个连接,这个许可将持续到这 个线程归还了连接。
在使用上,任何一个线程都需要通过acquire来获得一个Semaphore许可,这个操作可能会阻 塞线程直到成功获得一个许可,因为资源是有限的,所以许可也是有限的,没有获得资源就需 要阻塞等待其他线程归还Semaphore,而归还Semaphore操作通过release方法来进行, release会唤醒一个等待在Semaphore上的一个线程来尝试获得许可。
如果想要达到一种互斥的效果,比如任何时刻只能有一个线程获得许可,那么就可以初始化 Semaphore的数量为1,—个线程获得这个Semaphore之后,任何到来的通过acquire来尝试 获得许可的线程都会被阻塞直到这个持有Semaphore的线程调用了 release方法来释放 Semaphore。
在实现上,Semaphore借助了线程同步框架AQS, AQS的分析可以参考文章Java同步框架 AbstractQueuedSynchronizer,同样借助了AQS来实现的是java中的可重入锁的实现,同样 你可以在文章Java可重入锁详解中找到java中可重入锁的分析总结文档。在这些文章中已经 分析过如何通过AQS来实现锁的语义,本文将继续分析AQS的应用实例,Semaphore作为一种 线程间同步机制是非常轻量级的方案,所以学习和掌握Semaphore是有必要的。
信号量Semaphore
Semaphore的实现借助了同步框架AQS,下面的图片展示了 Semaphore的代码结构,Semaphore 使用一个内部类Sync来实现,而Sync继承了 AQS来实现,Sync有两个子类,分别对应着公 平模式和非公平模式的Semaphore。
Semaphore最常见的功能,不过其他方法还長需要我们去了解一下的
1、 acquire(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断。就 好比是一个学生占两个窗口。这同时也对应了相应的release方法。
2、 release(int permits)
释放给定数目的许可,将其返回到信号量。这个是对应于上面的方法,一个学生占几个窗口完 事之后还要释放多少
3、 availablePermits()
返回此信号量中当前可用的许可数。也就是返回当前还有多少个窗口可用。
4、 reducePermits(int reduction)
根据指定的缩减量减小可用许可的数目。
5、 hasQueuedThreads()
查询是否有线程正在等待获取资源。
6、 getQueueLength()
返回正在等待获取的线程的估计数目。该值仅是估计的数字。
7、 tryAcquire(int permits, long timeout, TimeUnit unit)
如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量 获取给定数目的许可。
8、 acquireUninterruptibly(int permits)
从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞。
基本上常见的使用方法都在这,Semaphore底层是由AQS和Uasafe完成的,篇幅问题在这里 不赘述了。感谢各位支持。
Was this helpful?
0 / 0