开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情
- Semaphore是一种在多线程环境下使用的设施,该设施负责协调各个线程,以保证它们能够正确、合理的使用公共资源的设施,也是操作系统中用于控制进程同步互斥的量。
- Semaphore是一种计数信号量,用于管理一组资源,内部是基于AQS的共享模式。它相当于给线程规定一个量从而控制允许活动的线程数。
- Semaphore用于限制可以访问某些资源(物理或逻辑的)的线程数目,他维护了一个许可证集合,有多少资源需要限制就维护多少许可证集合,假如这里有N个资源,那就对应于N个许可证,同一时刻也只能有N个线程访问。
- 一个线程获取许可证就调用acquire方法,用完了释放资源就调用release方法。
除了JDK定义的哪些锁,Semaphore也可以定义锁。Semaphore可以做的功能相当的多,比如秒杀限流
用Semaphore自定义Lock
public class SemaphoreTest {
public static void main(String[] args) {
final SemaphoreLock lock = new SemaphoreLock();
for (int i = 0; i < 2; i++) {
new Thread(()->{
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " get the lock.");
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName() + " release the lock.");
lock.unlock();
}
}).start();
}
}
static class SemaphoreLock{
private final Semaphore semaphore = new Semaphore(1);
public void lock() throws InterruptedException {
semaphore.acquire();
}
public void unlock() {
semaphore.release();
}
}
}
输出结果如下:
跟synchronized的区别
- 可以看出最大的区别就是可以控制多个线程访问多份资源,而不是只用一个线程访问一份资源
用Semaphore做限流
Semaphore可以控制多个线程访问多份资源,而不是只用一个线程访问一份资源,所以在限流方面也有应用。
重要方法
-
acquire():获取一个许可证,如果许可证用完了,则陷入阻塞。可以被打断。 -
release():释放一个许可证acquire(int permits)
public void release(int permits)
acquire多个时,如果没有足够的许可证可用,那么当前线程将被禁用以进行线程调度,并且处于休眠状态,直到发生两件事情之一:
- 一些其他线程调用此信号量的一个release方法,当前线程旁边将分配许可证,并且可用许可证的数量满足此请求;
- 要么一些其他线程interrupts当前线程。
release多个时,会使许可证增多,最终可能超过初始值