信号量,控制同时访问资源的线程个数。
在线程访问资源前,必须先从信号量中获取许可证(acquire()),当线程使用资源结束后,调用release()方法,会释放一个信号,以便其他的线程可以获取信号量。
共享型

源码分析

acquire()

在信号量池中获取一个信号,在获取许可之前一直阻塞,除非线程被中断

  1. public void acquire() throws InterruptedException {
  2. sync.acquireSharedInterruptibly(1);
  3. }
  1. final int nonfairTryAcquireShared(int acquires) {
  2. for (;;) {
  3. int available = getState();
  4. int remaining = available - acquires;
  5. if (remaining < 0 ||
  6. compareAndSetState(available, remaining))
  7. return remaining;
  8. }
  9. }

release()

释放一个许可,将其返回信号量。

使用场景

比如某个接口限制并发访问的线程数,在单点的情况下,可以使用信号量控制。

  1. private Semaphore semaphore = new Semaphore(2);
  2. private CountDownLatch countDownLatch = new CountDownLatch(3);
  3. public static void main(String[] args){
  4. SemaphoreDemo semaphoreDemo = new SemaphoreDemo();
  5. for (int i = 0; i < 3; i++) {
  6. new Thread(() -> {
  7. try {
  8. semaphoreDemo.semaphore.acquire();
  9. semaphoreDemo.countDownLatch.countDown();
  10. System.out.println(Thread.currentThread().getName() + "正在执行...");
  11. semaphoreDemo.semaphore.release();
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. },"Thread-" + i).start();
  16. }
  17. try {
  18. semaphoreDemo.countDownLatch.await();
  19. System.out.println(Thread.currentThread().getName() + "正在执行...");
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }