1. 類的定義
public class Semaphore implements java.io.Serializable
複製程式碼
2. 欄位屬性
//序列化版本號
private static final long serialVersionUID = -3222578661600680210L;
//同步器,AbstractQueuedSynchronizer的子類
private final Sync sync;
複製程式碼
從欄位屬性中可以看出
- Semaphore的所有操作都是使用內部類Sync物件進行操作的
3. 構造方法
//傳入訊號數
public Semaphore(int permits) {
//預設使用非公平鎖
sync = new NonfairSync(permits);
}
//傳入訊號數和鎖的型別
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
複製程式碼
從構造方法中可以看出
- 構造方法只做了一件事:初始化sync物件
4.方法
acquire 方法
//可中斷的獲取訊號量
public void acquire() throws InterruptedException {
//呼叫sync的acquireSharedInterruptibly方法
sync.acquireSharedInterruptibly(1);
}
//獲取指定數量的訊號量
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
//呼叫sync的acquireSharedInterruptibly方法
sync.acquireSharedInterruptibly(permits);
}
複製程式碼
acquireUninterruptibly 方法
//不可中斷的獲取訊號量
public void acquireUninterruptibly() {
//呼叫sync的acquireShared方法
sync.acquireShared(1);
}
//不可中斷的獲取指定數量的訊號量
public void acquireUninterruptibly(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireShared(permits);
}
複製程式碼
tryAcquire 方法
//嘗試獲取訊號量
public boolean tryAcquire() {
//呼叫sync的nonfairTryAcquireShared方法
return sync.nonfairTryAcquireShared(1) >= 0;
}
//嘗試獲取指定數量的訊號量
public boolean tryAcquire(int permits) {
if (permits < 0) throw new IllegalArgumentException();
//嘗試獲取指定數量的訊號量
return sync.nonfairTryAcquireShared(permits) >= 0;
}
//設定超時時間的嘗試獲取訊號量
public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
//呼叫sync的tryAcquireSharedNanos方法
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//設定超時時間的嘗試獲取指定數量的訊號量
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
//呼叫sync的tryAcquireSharedNanos方法
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
}
複製程式碼
release 方法
//釋放一個訊號量
public void release() {
//呼叫sync的releaseShared方法
sync.releaseShared(1);
}
//釋放指定數量的訊號量
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
複製程式碼
availablePermits 方法
//獲取當前可用的通道數
public int availablePermits() {
return sync.getPermits();
}
複製程式碼
drainPermits 方法
//獲取立即可用的通道數
public int drainPermits() {
return sync.drainPermits();
}
複製程式碼
reducePermits 方法
//減少訊號數
protected void reducePermits(int reduction) {
if (reduction < 0) throw new IllegalArgumentException();
sync.reducePermits(reduction);
}
複製程式碼
isFair 方法
//獲取鎖的型別, true 公平鎖, false 非公平鎖
public boolean isFair() {
return sync instanceof FairSync;
}
複製程式碼
hasQueuedThreads 方法
//佇列中是否有正在等訊號的執行緒
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
複製程式碼
getQueueLength 方法
//獲取佇列中等待訊號的執行緒數
public final int getQueueLength() {
return sync.getQueueLength();
}
複製程式碼
getQueuedThreads 方法
//獲取佇列中的執行緒,以集合的方式返回
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
複製程式碼
5. 內部類Sync
1. 類的定義
abstract static class Sync extends AbstractQueuedSynchronizer
複製程式碼
從類的定義中可以看出
- Sync是一個抽象的靜態內部類,使用模板方法的設計模式讓子類繼承
- Sync繼承AbstractQueuedSynchronizer類
2. 欄位屬性
//序列化版本號
private static final long serialVersionUID = 1192457210091910933L;
複製程式碼
3. 構造方法
//傳入的訊號數就是AQS中的state
Sync(int permits) {
setState(permits);
}
複製程式碼
4. 方法
getPermits 方法
//獲取訊號數
final int getPermits() {
//實質上就是獲取state的值
return getState();
}
複製程式碼
nonfairTryAcquireShared 方法
//非公平方式獲取共享鎖,返回剩餘可用訊號數
final int nonfairTryAcquireShared(int acquires) {
//for無限迴圈,自旋CAS
for (;;) {
//獲取當前的state
int available = getState();
//可用訊號-獲取數量=剩餘可用數量
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
複製程式碼
tryReleaseShared 方法
//嘗試釋放共享鎖
protected final boolean tryReleaseShared(int releases) {
//for無限迴圈,自旋CAS
for (;;) {
//獲取當前的state
int current = getState();
//可用訊號+釋放數量=新的可用數量
int next = current + releases;
if (next < current) // overflow
//releases小於0 丟擲異常
throw new Error("Maximum permit count exceeded");
//CAS,設定新值
if (compareAndSetState(current, next))
return true;
}
}
複製程式碼
reducePermits 方法
//減少訊號數量
final void reducePermits(int reductions) {
//for無限迴圈,自旋CAS
for (;;) {
//獲取當前的state
int current = getState();
//可用訊號-減少的數量=新的可用數量
int next = current - reductions;
if (next > current) // underflow
//reductions小於0 丟擲異常
throw new Error("Permit count underflow");
//CAS,設定新值
if (compareAndSetState(current, next))
return;
}
}
複製程式碼
drainPermits 方法
//清空訊號
final int drainPermits() {
//CAS 自旋把state置為0
for (;;) {
int current = getState();
if (current == 0 || compareAndSetState(current, 0))
return current;
}
}
複製程式碼
6. 內部類 NonfairSync
1. 類的定義
static final class NonfairSync extends Sync
複製程式碼
從類的定義可以看出
- NonfairSync是Sync的子類
2. 欄位屬性
//序列化版本號
private static final long serialVersionUID = -2694183684443567898L;
複製程式碼
3. 構造方法
//設定state
NonfairSync(int permits) {
super(permits);
}
複製程式碼
4. 方法
tryAcquireShared 方法
//嘗試獲取共享鎖
protected int tryAcquireShared(int acquires) {
//呼叫父類的方法nonfairTryAcquireShared,直接搶鎖
return nonfairTryAcquireShared(acquires);
}
複製程式碼
7. 內部類FairSync
1. 類的定義
static final class FairSync extends Sync
複製程式碼
從類的定義中可以看出
- FairSync繼承Sync類
2. 欄位屬性
//序列化版本號
private static final long serialVersionUID = 2014338818796000944L;
複製程式碼
3. 構造方法
//設定state
FairSync(int permits) {
super(permits);
}
複製程式碼
方法
tryAcquireShared 方法
//嘗試獲取共享鎖
protected int tryAcquireShared(int acquires) {
for (;;) {
//先看佇列中是否有執行緒排隊
if (hasQueuedPredecessors())
return -1;
//獲取state的值
int available = getState();
//可用訊號-獲取數量=剩餘可用數量
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
複製程式碼