源碼解析
Semaphore(信號量),這個類是用來控制并發(fā)時線程的數(shù)量的绳军,首先這個類是實現(xiàn)了序列化接口
public class Semaphore implements Serializable
(序列化)
我們主要來看看內(nèi)部的一個結構和主要的方法acquire(獲得)和release(釋放)方法
其中這個類中有幾個內(nèi)部類映挂,首先是抽象類 Sync 繼承了同步器峦甩,
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
//構造方法藏鹊,設置了同步狀態(tài)的值
Sync(int permits) {
setState(permits);
}
//返回當前的同步狀態(tài)的值
final int getPermits() {
return getState();
}
//嘗試獲取不公平的鎖
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
//得到的同步狀態(tài)的值
int available = getState();
//根據(jù)得到的值嘗試修改同步狀態(tài)的值
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
//嘗試釋放鎖
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//獲取當前同步狀態(tài)的值
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
// 根據(jù)得到的值嘗試修改同步狀態(tài)的值
if (compareAndSetState(current, next))
return true;
}
}
//減少同步狀態(tài)值
final void reducePermits(int reductions) {
for (;;) {
int current = getState();
int next = current - reductions;
if (next > current) // underflow
throw new Error("Permit count underflow");
if (compareAndSetState(current, next))
return;
}
}
//返回剩余的同步狀態(tài)值
final int drainPermits() {
for (;;) {
int current = getState();
if (current == 0 || compareAndSetState(current, 0))
return current;
}
}
}
然后分別有兩個靜態(tài)的內(nèi)部類 NonfairSync(不公平模式)和FairSync(公平模式)實現(xiàn)了抽象類Sync,可以看到分別重寫了同步器中的tryAcquireShared方法魄咕,下面是源碼
static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L;
//調(diào)用了父類的構造函數(shù)
NonfairSync(int permits) {
super(permits);
}
//嘗試獲取鎖,實際調(diào)用父類的nonfairTryAcquireShared方法
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
}
/**
* Fair version
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L;
//調(diào)用了父類的構造方法
FairSync(int permits) {
super(permits);
}
//可以看到和父類的方法中蚌父,只是多了一個hasQueuedPredecessors方法來先判斷當前的
// 對列中是否還有任務
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;
}
}
接下來是構造方法
//默認創(chuàng)建一個同步狀態(tài)值為permits的不公平模式
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
//根據(jù)boolean判斷生成不公平還是公平的模式
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
然后是acquire() 方法
//設置每個線程每個線程需要占用的同步狀態(tài)值 默認為1
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//自定義每個線程每個線程需要占用的同步狀態(tài)值
public void acquire(int permits) throws InterruptedException {
//必須大于0哮兰,否則拋出異常
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
然后是release方法
//釋放當前線程所占用的同步狀態(tài)值,默認為1
public void release() {
sync.releaseShared(1);
}
//釋放當前線程所占用的同步狀態(tài)值
public void release(int permits) {
//必須大于0 否則拋出異常
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
下面是一個Semaphore使用的示例
public class Demo extends Thread {
private Semap semap;
public Demo(Semap semap){
this.semap=semap;
}
@Override
public void run(){
semap.Test();
}
}
public class Semap {
//設置一個同步值為3的Semaphore
Semaphore semaphore=new Semaphore(3);
public void Test(){
try {
//設置每個線程要占用的同步值 默認為1
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 開始: " + LocalTime.now());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 結束: " + LocalTime.now());
//釋放所占用的狀態(tài)值
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//運行
public class SemaphoreDemo{
public static void main(String[] args) {
Semap semap=new Semap();
for(int i=0;i<5;i++){
new Demo(semap).start();
}
}
}
//運行結果
Thread-0 開始: 15:35:38.643
Thread-1 開始: 15:35:38.643
Thread-2 開始: 15:35:38.643
Thread-0 結束: 15:35:39.643
Thread-1 結束: 15:35:39.643
Thread-2 結束: 15:35:39.643
Thread-4 開始: 15:35:39.643
Thread-3 開始: 15:35:39.643
Thread-3 結束: 15:35:40.644
Thread-4 結束: 15:35:40.644
總結
可以看出來其實Semaphore內(nèi)部其實是根據(jù)同步狀態(tài)的值來限制并發(fā)的時線程的數(shù)量苟弛,當同步狀態(tài)值為0時喝滞,后來的線程將被阻塞,直到有線程釋放膏秫。