网站接任务来做,简约好看的网站模板,一些你不知道的网站,工信部备案系统官网简单概括#xff1a;
Semphore是一把共享锁#xff08;即读锁#xff09;#xff0c;即实现了AQS的tryAcquireSharedtryReleaseShared函数Semphore的逻辑是这样#xff1a;
创建semphore的时候会初始化一个锁容量即permits#xff0c;即最多同时允许permits个…简单概括
Semphore是一把共享锁即读锁即实现了AQS的tryAcquireSharedtryReleaseShared函数Semphore的逻辑是这样
创建semphore的时候会初始化一个锁容量即permits即最多同时允许permits个线程获取读锁资源。AQS的state在semphore中表示锁资源的剩余容量。Semphore.tryAcquireShared就是如果锁资源剩余容量大于0则表示可以成功获取锁然后锁资源容量减一Semphore的tryReleaseShared就是锁资源容量1。笔记
semphore没有锁所有者的概念只有资源剩余量的概念也就是说不管你是谁只要资源还有剩余那么就允许访问也就是说一个线程可以获取多次资源import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;public class Semaphore implements java.io.Serializable {private static final long serialVersionUID -3222578661600680210L;private final Sync sync;abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID 1192457210091910933L;Sync(int permits) {//state就是表示锁资源剩余量setState(permits);}final int getPermits() {return getState();}//尝试获取共享锁资源。while cas方式扣减准确说是do{}while(!CAS)//获取锁资源的逻辑就是如果锁资源剩余容量大于0就允许立即获得锁而无需入aqs队列排队//反之则获取失败返回false//semphore没有锁所有者的概念只有资源剩余量的概念//也就是说不管你是谁只要资源还有剩余那么就允许访问//也就是说一个线程可以获取多次资源final int nonfairTryAcquireShared(int acquires) {for (;;) {//笔记getState是非并发安全的但是没关系//因为getState的返回值只是用来快速判断是否有资源剩余//真正决定能否成功获得锁的还是cas(available,remainging)这个操作//也就是说这里是一个乐观的做法先扣减再写回如果冲突了就重试//通过getState获取资源剩余量int available getState();//先计算要扣减的资源量int remaining available - acquires;//如果remaining小于0表示资源剩余量小于0则此时无法成功获取锁所以返回负数//如果compareAndSetState(available, remaining)成功则表明资源剩余量大于0//并且资源扣减成功此时remaing大于等于0表示获取锁成功所以返回非负数if (remaining 0 ||compareAndSetState(available, remaining))return remaining;//走到这里则进入下一轮循环重试}}//尝试释放锁资源也是do{}while(!cas)方式增加锁资源//因为是共享锁且没有所有者的概念所以可以一个线程多次释放//每次释放都会锁资源1甚至能无线多次释放然后就能无限获取了也就是卡bug了//如下所示信号量最初资源容量限制为2但是因为没有锁所有者的概念以及上限检测//所以直接release(100)即增加100个令牌这样就能获取102个令牌而不会阻塞// Semaphore semnew java.util.concurrent.Semaphore(2);// sem.release(100);// for(int i0;i102;i){// sem.acquire();// }protected final boolean tryReleaseShared(int releases) {for (;;) {//读取锁资源状态int current getState();//计算更新后的锁资源量int next current releases;if (next current) throw new Error(Maximum permit count exceeded);//cas方式更新锁资源状态if (compareAndSetState(current, next))return true;//走到这里则进入下一轮循环重试}}//扣减锁资源也是通过do{}while(!CAS)方式更新final void reducePermits(int reductions) {for (;;) {int current getState();int next current - reductions;if (next current) throw new Error(Permit count underflow);if (compareAndSetState(current, next))return;}}//清空锁资源。就是把state设置为0也是通过do{}while(!CAS)方式更新final int drainPermits() {for (;;) {int current getState();if (current 0 || compareAndSetState(current, 0))return current;}}}static final class NonfairSync extends Sync {private static final long serialVersionUID -2694183684443567898L;NonfairSync(int permits) {super(permits);}//非公平方式获取锁资源就是如果有锁资源剩余容量大于0就允许立即获得锁而无需入aqs队列排队protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires);}}static final class FairSync extends Sync {private static final long serialVersionUID 2014338818796000944L;FairSync(int permits) {super(permits);}//公平方式获取锁资源先来先服务的原则。//也就是说只要aqs队列不为空则说明在本线程之前有其他线程已经在排队了//公平的原则就是先来先服务所以这里就直接返回false表示获取锁失败//一旦tryAcquireShared返回失败则aqs会把该节点丢到aqs list的最末尾protected int tryAcquireShared(int acquires) {for (;;) {//判断是有在此之前有其他线程等待获取锁资源即信号量if (hasQueuedPredecessors())//如果有则返回false表获取锁资源失败return -1;//如果在此之前没有其他线程等待获取锁资源即信号量//则通过do{}while(!CAS)扣减锁资源int available getState();int remaining available - acquires;if (remaining 0 ||compareAndSetState(available, remaining))return remaining;}}}public Semaphore(int permits) {sync new NonfairSync(permits);}public Semaphore(int permits, boolean fair) {sync fair ? new FairSync(permits) : new NonfairSync(permits);}//下面的函数都输对sync的一个简单封装所以下面的函数就没注释了一眼就能看明白public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);}public void acquireUninterruptibly() {sync.acquireShared(1);}public boolean tryAcquire() {return sync.nonfairTryAcquireShared(1) 0;}public boolean tryAcquire(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}public void release() {sync.releaseShared(1);}public void acquire(int permits) throws InterruptedException {if (permits 0) throw new IllegalArgumentException();sync.acquireSharedInterruptibly(permits);}public void acquireUninterruptibly(int permits) {if (permits 0) throw new IllegalArgumentException();sync.acquireShared(permits);}public boolean tryAcquire(int permits) {if (permits 0) throw new IllegalArgumentException();return sync.nonfairTryAcquireShared(permits) 0;}public boolean tryAcquire(int permits, long timeout, TimeUnit unit)throws InterruptedException {if (permits 0) throw new IllegalArgumentException();return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));}public void release(int permits) {if (permits 0) throw new IllegalArgumentException();sync.releaseShared(permits);}public int availablePermits() {return sync.getPermits();}public int drainPermits() {return sync.drainPermits();}protected void reducePermits(int reduction) {if (reduction 0) throw new IllegalArgumentException();sync.reducePermits(reduction);}public boolean isFair() {return sync instanceof FairSync;}public final boolean hasQueuedThreads() {return sync.hasQueuedThreads();}public final int getQueueLength() {return sync.getQueueLength();}protected CollectionThread getQueuedThreads() {return sync.getQueuedThreads();}public String toString() {return super.toString() [Permits sync.getPermits() ];}
}