Java并发编程(四)--Semaphore

来源:互联网 发布:多组数据的差异性分析 编辑:程序博客网 时间:2024/06/06 00:44

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阅读。
这里写图片描述
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章节的可以略过
acquire
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;     } }
阅读全文
0 0
原创粉丝点击