Semaphore
Semaphore 完成的功能是信号量的操作,用于表示一个资源还剩多少使用量,常用于数据库限流之类的场景
其底层是 AQS 实现的,state 在其中扮演的角色就是信号量,当其为 0 的时候就将后续来访问的线程加入到阻塞队列中,有人释放信号量的时候去唤醒队列中的线程
其有两种方式;公平和非公平,在其初始化的时候可以指定,默认为非公平的:
- 初始化只传入一个 int 值,表示有多少信号量,有趣的是,这个玩意可以是负数,也就是说,系统必须先还回去一定数量的信号量,这个系统才可以运营,所以他不检测是否是合法归还
- 如果额外传入一个布尔值,则表示是否为公平锁
如果这个锁是非公平的,他去获取信号量的时候会去直接 CAS 这个 state 变量,而不会去看看有没有人在 CLH 队列中待着,而,公平锁会检查一下队列中是否有人,有人的话就去排队,没人的话就去 CAS state
Sync 在其基础上增加了几个方法:
- nonfairTryAcquireShared(非公平扣减):它适用于非公平扣减的情况,作用就是一直抢占指定数量的信号量,直到抢到或者是变成负的,如果是负的就说明没抢到,去排队吧,如果是正数,说明抢到了,美滋滋
- tryAcquireShared(公平扣减):他会先检查队列中是否有等待的线程,有就返回 -1 去排队
- tryReleaseShared(归还):增加指定的信号量,其中还有上溢检查,上溢了会报错,成功了返回 true
- reducePermits(消除):直接消除指定的信号量,还有下溢检查,下溢了也会报错
- drainPermits(清空):将当前的信号量置为0,并返回收缴的信号量的数目
基于 Sync 提供的一些基础方法,他其提供了很完备的获取、释放方法,这里说说重要的:
- acquireUninterruptibly():这个方法不响应线程中断,直到获取到了信号量
- tryAcquire():试试有没有信号量,返回布尔值表示是否拿到了,适合快速失败的场景
- tryAcquire(long timeout, TimeUnit unit):等一段时间,没等到就撤退