Java并发编程(四)--Semaphore

1.简介

java.util.concurrent.Semaphore是一个计数信号量类,维持一个许可集合。每个acquire方法调用如果必要会阻塞直到获得一个可用许可。每个release调用增加一个许可。
在创建时可以传入int permits许可数、boolean fair是否公平,总体结构和可重入锁ReentrantLock类似,内部维持一个Semaphore.Sync类型同步器,有公平模式FairSync、不公平模式NonfairSync两种实现。在构造方法中根据fair创建

 public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

2.类结构

Semaphore.Sync继承自AbstractQueuedSynchronizer,实现了AbstractQueuedSynchronizer共享模式获取资源,如果不懂AbstractQueuedSynchronizer机制可以返回第一章AbstractQueuedSynchronizer阅读。
Java并发编程(四)--Semaphore_第1张图片
Semaphore.Sync 构造时传入permits对应AbstractQueuedSynchronizer的state属性

 Sync(int permits) {
     setState(permits);
 }

Semaphore.acquire(int permits) 实际调用sync的acquireSharedInterruptibly方法,之后state=state-permits;
Semaphore.release(int permits) 则state=state+permits

public void acquire(int permits) throws InterruptedException {
 if (permits < 0) throw new IllegalArgumentException();
    sync.acquireSharedInterruptibly(permits);
}
public void release(int permits) {
 if (permits < 0) throw new IllegalArgumentException();
 sync.releaseShared(permits);
}

关键方法:
Sync

  • nonfairTryAcquireShared 不公平共享模式尝试获取许可
  • tryReleaseShared 尝试释放锁

NonfairSync

  • tryAcquireShared 不公平共享模式尝试获取许可,直接使用父类Sync的nonfairTryAcquireShared 方法

FairSync

  • tryAcquireShared 公平共享模式尝试获取许可。

3.aqs acquireSharedInterruptibly流程

共享获取资源方式acquireSharedInterruptibly流程和acquireInterruptibly大致相同,以下是aqs中的独占模式流程图,共享模式基本一样就不另外画了。已看过aqs章节的可以略过
Java并发编程(四)--Semaphore_第2张图片
acquireShared和acquireSharedInterruptibly的不同点在于线程被中断后acquireSharedInterruptibly抛出InterruptedException异常,而acquireShared忽略中断状态继续执行获取资源循环。

3.不公平模式源码

Sync.nonfairTryAcquireShared实现了不公平获取资源的。

 final int nonfairTryAcquireShared(int acquires) {
     for (;;) {//死循环直至结束
         int available = getState();//当前许可数
         int remaining = available - acquires;//成功后剩余许可数
         //remaining < 0 资源超过限制,返回负数代表不成功
         if (remaining < 0 ||
             compareAndSetState(available, remaining))//CAS设置剩余资源数,成功返回,不成功继续循环尝试
             return remaining;
     }
 }

NonfairSync.tryAcquireShared直接使用Sync.nonfairTryAcquireShared

 protected int tryAcquireShared(int acquires) {
     return nonfairTryAcquireShared(acquires);
 }

4.公平模式源码

FairSync.tryAcquireShared方法实现的公平模式稍有不同,区别只在公平模式会判断当前线程之前是否还有等待者,有则直接返回获取失败

 protected int tryAcquireShared(int acquires) {
     for (;;) {//死循环直至结束
         if (hasQueuedPredecessors())//如果当前线程之前还有等待线程,直接返回失败
             return -1;
         int available = getState();//当前许可数
         int remaining = available - acquires;//成功后剩余许可数
         //remaining < 0 资源超过限制,返回负数代表不成功
         if (remaining < 0 ||
             compareAndSetState(available, remaining))//CAS设置剩余资源数,成功返回,不成功继续循环尝试
             return remaining;
     }
 }

你可能感兴趣的:(java并发编程)