1. 信号量类 Semaphore
的作用是
- 限制对资源的并发访问数
2. 信号量类 Semaphore
的使用场景是
- 现实中,资源往往有多个,但每个同时只能被一个线程访问。比如,饭店的饭桌、火车上的卫生间
- 有的单个资源即使可以被并发访问,但并发访问次数多了可能影响性能,所以希望限制并发访问的线程数
- 还有,与软件的授权和计费有关,对不同等级的账户,限制不同的最大并发访问数
3. Semaphore
的构造方法
public Semaphore(int permits)/public Seamphore(int permits, boolean fair)
fair
表示公平;permits
表示许可数量
4. Semaphore
的主要方法有
public void acquire() throws InterruptedException
:阻塞获取许可public void acquireUninterruptibly()
:阻塞获取许可,不响应中断public void acquire(int permits) throws InterruptedException
:批量获取多个许可public void acquireUninterruptibly(int permits)
:批量获取多个,不响应中断public boolean tryAcquire()
:尝试获取public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
:限定等待时间获取public void release()
:释放许可
5. 写一个信号量类 Semaphore
的 Demo
1 | public class AccessControlService { |
6. 如果设置 permits
的数量为 1,那 Semaphore
和一般的锁的区别是
一般锁只能由持有锁的线程释放,而
Semaphore
表示的只是一个许可数,任意线程都可以调用其release()
方法主要的锁实现类
ReentrantLock
是可重入的;而Semaphore
不是可重入的,每一次的acquire()
调用都会消耗一个许可举例,下面程序会阻塞在第二个
acquire()
调用,永远都不会输出acquire
1
2
3
4Semaphore permits = new Semaphore(1);
permits.acquire();
permits.acquire();
System.out.println("acquired");
7. 信号量 Semaphore
的基本原理
- 原理比较简单,也是基于 AQS 实现的
- AQS:并发工具
ReentrantReadWriteLock
、Semaphore
、CountDownLatch
,它们的实现有很多类似的地方。为了复用代码,Java 提供了一个抽象类AbstractQueuedSynchronizer
,简称 AQS,简化了并发工具的实现 permits
表示共享的锁个数acquire()
方法就是检查锁个数是否大于 0,大于则减一,获取成功,否则就等待release()
方法就是将锁个数加一,唤醒第一个等待的线程