Semaphore 在项目中使用很少,直到我读了一个开源项目,原来 Semaphore 可以被恰当地使用的。
一、Semaphore 简介
Semaphore
(信号量)是一种计数器,用于限制同时访问特定资源或执行某段代码的线程数量。
它内部维护了一个许可的数量,每当一个线程进入需要被保护的代码块时,就尝试获取一个许可或者多个;当离开这个代码块时,则释放该许可。
如果所有许可都被占用,那么新请求许可的线程将等待。
Semaphore信号量与 CountDownLatch 不同的是,它内部的计数器是递增的,并且在一开始初始化允许的最大值。
二、初识 Semaphore
第一次正式认识 Semaphore 还是在一款开源软件上。
项目地址:gitee.com/uzongn/java…(fork到自己的仓库了)
项目简单介绍: Aliyun LOG Java Producer 是一个易于使用且高度可配置的 Java 类库,专门为运行在大数据、高并发场景下的 Java 应用量身打造。
2.1 Semaphore 的用途
用于控制正在发送空间的大小,类似于限流。 在这个开源软件它是这么使用的。下面是参数说明:maxBlockMs 表示最大的可用空间
类的位置:com.aliyun.openservices.aliyun.log.producer.LogProducer
memoryController 用于控制当前机器中正在发送中的日志内存总大小。
com.aliyun.openservices.aliyun.log.producer.internals.LogAccumulator
在这段逻辑中, 由于发送的日志是并发的,为了防止发送占用内存过大, Semaphore 类型的变量 memoryController,用于控制正在发送的内存总大小。 这样避免过多的发送线程发送日志,导致内存溢出。
简而言之:限流,限制发送日志的内存占用量。
三、Semaphore 使用注意事项
Semaphore
调用acquire()
获取许可, try ... finally
在finally
中释放许可。通常建议放在 finally 代码块中。
调用acquire()
可能会进入等待,直到满足条件为止。也可以使用tryAcquire()
指定等待时间:
另外:避免线程等待,可以设置最长等待时长。
获取许可不允许设置负数。
public boolean tryAcquire(int permits) {
if (permits < 0) throw new IllegalArgumentException();
return sync.nonfairTryAcquireShared(permits) >= 0;
}
四、应用场景
根据 Semaphore 的特性,可以围绕 “限流” 场景,进行合理的落地。(注意是虚拟机级别的,非分布式)
五、Semaphore 内部结构
Semaphore
的核心在于其内部类Sync
,它继承自AbstractQueuedSynchronizer
(AQS),这是其核心。Sync
类通过getState()
和setState(int newState)
方法管理许可数量。
- 非公平模式:
NonfairSync
类通过nonfairTryAcquireShared(int acquires)
和nonfairTryReleaseShared(int releases)
方法实现许可的获取和释放,这种方式下,线程的调度可能不是公平的。 - 公平模式:
FairSync
类通过tryAcquireShared(int acquires)
和tryReleaseShared(int releases)
方法实现许可的获取和释放,这种方式下,线程调度是公平的,即按照线程等待的顺序来分配许可。
默认是:非公平模式
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
公平策略: 看当前线程节点的前驱节点是否也在等待获取该资源,如果是则放弃获取的权限,然后加入 AQS 阻塞队列,否则就直接获取。
六、总结
Semaphore 跟 CountDownLatch 一样,都复用 AQS 的能力。 另外都使用for(;;)
自旋 ,compareAndSetState
对 state 进行安全操作
整体上而言,Semaphore 在使用限流上经常被其他工具所替代,比如 guava#Ratelimiter 限流工具。所以在使用上不多。感兴趣可以再深入挖掘。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21102,转载请注明出处。
评论0