作用
主要运用共享锁机制;
控制同时访问某个特定资源的线程数量,用在流量控制,通过state值判断,如果state>0,允许新的线程执行;如果state=0,不允许新的线程执行,循环执行是考虑多线程环境下条件不满足时重新获取
1)获取锁根据acquire()中 int remaining = available(当前state) - acquires(方法sync.acquireSharedInterruptibly(1)里的参数值1)
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 || //当前state=0,不允许新的线程执行
compareAndSetState(available, remaining)) //当前state>0,允许新的线程执行
return remaining;
}
}
如果state数量<0,就会阻塞加入等待队列 ,否则执行成功
2)释放锁根据acquire()中 int next = current(当前state) + releases(方法sync.releaseShared(1)里的参数值1)
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;
}
}
如果compareAndSetState(current, next)成功,就会 结束返回
案例
public class DBPoolSemaphore {
private final static int POOL_SIZE = 10;
private final Semaphore useful,useless;//useful表示可用的数据库连接,useless表示已用的数据库连接
public DBPoolSemaphore() {
this. useful = new Semaphore(POOL_SIZE);
this.useless = new Semaphore(0);
}
//存放数据库连接的容器
private static LinkedList<Connection> pool = new LinkedList<Connection>();
//初始化池
static {
for (int i = 0; i < POOL_SIZE; i++) {
pool.addLast(SqlConnectImpl.fetchConnection());
}
}
/*归还连接*/
public void returnConnect(Connection connection) throws InterruptedException {
if(connection!=null) {
System.out.println("当前有"+useful.getQueueLength()+"个线程等待数据库连接!!"
+"可用连接数:"+useful.availablePermits());
useless.acquire();
synchronized (pool) {
pool.addLast(connection);
}
useful.release();
}
}
/*从池子拿连接*/
public Connection takeConnect() throws InterruptedException {
useful.acquire();
Connection conn;
synchronized (pool) {
conn = pool.removeFirst();
}
useless.release();
return conn;
}
}
在使用Semaphore时,初始化state值,获取锁就-1,释放锁就+1,根据state<0值判断是否能继续获得锁