javalock(四)AQS派生类之Semphore逐行注释

简单概括:

Semphore是一把共享锁(即读锁),即实现了AQS的tryAcquireShared&&tryReleaseShared函数

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,但是因为没有锁所有者的概念以及上限检测
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值