Semaphore

51 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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();
        }
    }
}

输出结果如下:

image.png

跟synchronized的区别

  • 可以看出最大的区别就是可以控制多个线程访问多份资源,而不是只用一个线程访问一份资源

用Semaphore做限流

Semaphore可以控制多个线程访问多份资源,而不是只用一个线程访问一份资源,所以在限流方面也有应用。

重要方法

  • acquire()获取一个许可证,如果许可证用完了,则陷入阻塞。可以被打断。

  • release()释放一个许可证

    acquire(int permits)
    public void release(int permits)

acquire多个时,如果没有足够的许可证可用,那么当前线程将被禁用以进行线程调度,并且处于休眠状态,直到发生两件事情之一:

  • 一些其他线程调用此信号量的一个release方法,当前线程旁边将分配许可证,并且可用许可证的数量满足此请求;
  • 要么一些其他线程interrupts当前线程。

release多个时,会使许可证增多,最终可能超过初始值