使用Demo

  1. public class SemaphoreDemo {
  2. public static void main(String[] args) {
  3. int size = 10;
  4. Semaphore semaphore = new Semaphore(2);
  5. for (int i = 0; i < size; i++) {
  6. new Thread(()->{
  7. try {
  8. semaphore.acquire(2);
  9. System.out.println(Thread.currentThread().getName() + " TODO logic ...");
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. } finally {
  13. semaphore.release(2);
  14. }
  15. }).start();
  16. }
  17. }
  18. }

原理简述

  1. AQS内部维护一个state值和一个阻塞队列
  2. 当某个线程调用Semaphore#acquire()方法的时候,首先会先判断state-2后,是否小于0,如果小于0,不做CAS修改动作,而是直接进入阻塞对列并挂起线程;如果state-2后大于0,并且CAS操作修改state值成功,继续执行,否则入队挂起。
  3. 当某个线程调用Semaphore#release();方法的时候,首先会尝试做state+2,如果CAS修改state值成功,并唤醒阻塞队列中的线程,CAS失败自旋重复之前的操作

公平和非公平模式

SemaphoreReentrantLock很像,也支持公平和非公平模式,假设是公平模式,会先看队列是否有阻塞线程,如果有,先去排队等待别的线程某个时机唤醒自己;如果非公平模式,会首先尝试修改state状态值,如果修改成功,可继续执行,否则乖乖排队并阻塞。

源码解读

待补充…