使用Demo
public class SemaphoreDemo {public static void main(String[] args) {int size = 10;Semaphore semaphore = new Semaphore(2);for (int i = 0; i < size; i++) {new Thread(()->{try {semaphore.acquire(2);System.out.println(Thread.currentThread().getName() + " TODO logic ...");} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release(2);}}).start();}}}
原理简述
- AQS内部维护一个
state值和一个阻塞队列。 - 当某个线程调用
Semaphore#acquire()方法的时候,首先会先判断state-2后,是否小于0,如果小于0,不做CAS修改动作,而是直接进入阻塞对列并挂起线程;如果state-2后大于0,并且CAS操作修改state值成功,继续执行,否则入队挂起。 - 当某个线程调用
Semaphore#release();方法的时候,首先会尝试做state+2,如果CAS修改state值成功,并唤醒阻塞队列中的线程,CAS失败自旋重复之前的操作
公平和非公平模式
Semaphore和ReentrantLock很像,也支持公平和非公平模式,假设是公平模式,会先看队列是否有阻塞线程,如果有,先去排队等待别的线程某个时机唤醒自己;如果非公平模式,会首先尝试修改state状态值,如果修改成功,可继续执行,否则乖乖排队并阻塞。
源码解读
待补充…
