Semaphore的使用
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
private final static int SEM_SIZE = 10;
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS");
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(SEM_SIZE);
MyThread thread1 = new MyThread("test1",semaphore);
MyThread thread2 = new MyThread("test2",semaphore);
thread1.start();
thread2.start();
int permits = 5;
System.out.println(prinDate() + Thread.currentThread().getName() + " trying to acquire!");
try {
semaphore.acquire(permits);
System.out.println(prinDate() + Thread.currentThread().getName() + " acquire successfully!");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
System.out.println(prinDate() + Thread.currentThread().getName() + " release successfully!");
}
}
static class MyThread extends Thread{
private Semaphore semaphore;
public MyThread(String name,Semaphore semaphore){
super(name);
this.semaphore = semaphore;
}
@Override
public void run() {
int count = 5;
System.out.println(prinDate() + Thread.currentThread().getName() + " trying to acquire!");
try {
semaphore.acquire(count);
System.out.println(prinDate() + Thread.currentThread().getName() + " acquire successfully!");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release(count);
System.out.println(prinDate() + Thread.currentThread().getName() + " release successfully!");
}
}
}
private static String prinDate(){
return simpleDateFormat.format(new Date()) + " ";
}
}
Semaphore类图
Semaphore类的声明
public class Semaphore implements java.io.Serializable
Semaphore类的内部类
Semaphore总共Sync、NonfairSync、FairSync三个内部类,并且三个内部类是紧密相关,NonfairSync和FairSync继承自AQS,Sync继承自AbstractQueuedSynchronizer抽象类。
Sync源码解析
/**
*内部类Sync继承自AQS
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
//构造器
Sync(int permits) {
setState(permits);
}
//获取许可
final int getPermits() {
return getState();
}
//共享模式下非公平方式获取资源
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//获取许可数
int available = getState();
//剩余的许可
int remaining = available - acquires;
//许可小于0或者CAS设置状态成功
if (remaining < 0 ||
compareAndSetState(available, remaining))
//返回remaining
return remaining;
}
}
/**
*共享模式下非公平方式获取资源
*/
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//获取许可数
int current = getState();
//增加可用的许可
int next = current + releases;
//溢出的情况
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
//如果CAS设置成功
if (compareAndSetState(current, next))
//返回true
return true;
}
}
/**
*减少许可数
*/
final void reducePermits(int reductions) {
for (;;) {
//获取许可
int current = getState();
//剩余可用的许可
int next = current - reductions;
if (next > current) // underflow
throw new Error("Permit count underflow");
//如果CAS成功
if (compareAndSetState(current, next))
//返回
return;
}
}
/**
*获取并返回所有许可
*/
final int drainPermits() {
for (;;) {
//获取许可数
int current = getState();
//如果current等于0或者CAS成功
if (current == 0 || compareAndSetState(current, 0))
//返回current
return current;
}
}
NonfairSync源码解析
NonfairSync类继承了Sync类,表示非公平策略获取资源,其只有一个tryAcquireShared()方式,重写了AQS的tryAcquireShared()方法:
/**
*非公平锁
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
//构造器
NonfairSync(int permits) {
super(permits);
}
//共享模式下获取资源
protected int tryAcquireShared(int acquires) {
//调用父类Sync中的nonfairTryAcquireShared()方法
return nonfairTryAcquireShared(acquires);
}
}
FairSync源码解析
FairSync类继承了Sync类,表示公平策略获取资源,其只有一个tryAcquireShared()方法,重写了AQS的tryAcquireShared()方法:
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
//构造器
FairSync(int permits) {
super(permits);
}
//共享模式下获取资源
protected int tryAcquireShared(int acquires) {
for (;;) {
//同步队列存在比当前线程等待更久的线程
//如果存在则返回-1
if (hasQueuedPredecessors())
return -1;
//获取state状态
int available = getState();
//剩余的许可
int remaining = available - acquires;
//如果剩余许可小于0或者CAS成功
if (remaining < 0 ||
compareAndSetState(available, remaining))
//返回remaining
return remaining;
}
}
}
Semaphore类的属性
//序列化ID
private static final long serialVersionUID = -3222578661600680210L;
//Sync对象
private final Sync sync;
Semaphore自身只有两个属性,最重要的是Sync属性,基于Semaphore对象的操作绝大多数都转移到了对Sync的操作。
Semaphore类的构造器
/**
*创建具有给定的许可数的非公平模式的Semaphore
*/
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
/**
* 创建具有给定的许可数和给定的参数的模式的Semaphore
*/
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
Semaphore类的非公平模式获取许可源码解析
/**
*获取一个许可
*/
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
*获取多个许可
*/
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
acquire()调用父类AQS中的acquireSharedInterruptibly()方法:
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
//如果线程已经被中断
if (Thread.interrupted())
//抛出InterruptedException异常
throw new InterruptedException();
//trytryAcquireShared()方法需要子类实现
//如果tryAcquireShared()方法返回小于0
//则获取资源失败
if (tryAcquireShared(arg) < 0)
//调用doAcquireSharedInterruptibly()方法
doAcquireSharedInterruptibly(arg);
}
acquireSharedInterruptibly()方法调用的tryAcquireShared()方法在非公平模式下的实现:
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
tryAcquireShared()方法调用的nonfairTryAcquireShared()方法实现如下:
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
tryAcquireShared()方法返回小于0,则获取资源失败。执行doAcquireSharedInterruptibly()方法:
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
最终可以获取大致的方法调用序列(假设使用非公平策略):
Semaphore类的非公平模式释放许可源码解析
//释放1个许可
public void release() {
sync.releaseShared(1);
}
//释放多个许可
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
release()方法调用AQS中的releaseShared()方法:
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
tryReleaseShared()方法需要子类实现:
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
}
如果tryReleaseShared()方法返回true将执行:
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
Semaphore类的公平模式获取许可源码解析
protected int tryAcquireShared(int acquires) {
for (;;) {
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
与非公平模式相比,公平模式多了hasQueuedPredecessors()方法调用。
Semaphore类的公平模式释放许可源码解析
公平模式的释放许可与非公平模式释放许可源码相同。