Semaphore源码分析

还是像之前,关于Semaphore的使用方法,我就不介绍了,依然提供一个博客地址供大家了解。https://blog.csdn.net/zzy7075/article/details/52095773

平常的使用的话:

`

//permits是指允许进入的线程数量
Semaphore semaphore=new Semaphore(permits);
semaphore.acquire();//还有acquire(permits);区别在于acquire获取一个,acquire(permits)获取多个
semaphore.release();//还有release(permits);同理

1.那么还是从构造方法入手。

public Semaphore(int permits) {
    //sync继承aqs,基本做的就是setState(permits)
    sync = new NonfairSync(permits);
}

2.先从acquire()入手,感觉两个方法的实现应该一样。

public void acquire() throws InterruptedException {
    //默认获取一个许可
    sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}
//先看tryAcquireShared(arg)这个方法。
protected int tryAcquireShared(int acquires) {
    return nonfairTryAcquireShared(acquires);
}
final int nonfairTryAcquireShared(int acquires) {
    //从这个死循环当中可以看出3中情况,
    //(1)负数:导致走doAcquireSharedInterruptibly
    //(2)0:成功获取许可,结束
    //(3)正数:成功获取许可,结束
    for (;;) {
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 ||  compareAndSetState(available, remaining))
            return remaining;
    }
}
//那么就需要看一下(1)情况了。
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    /**
     *大致讲一下流程:将node放入等待队列当中,当node是老二的时候,就可以尝试去获取了,
     *其余时候,就应该阻塞了。
     */
    try {
        for (;;) {
            final Node p = node.predecessor();
            if (p == head) {
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    setHeadAndPropagate(node, r);
                    p.next = null; 
                    // help GC
                    failed = false;
                    return;
                }
            }
            if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

2.看一下acquire(permits)

//好了,GG,一模一样了
public void acquire(int permits) throws InterruptedException {
    if (permits < 0) 
        throw new IllegalArgumentException();
    sync.acquireSharedInterruptibly(permits);
}

3.release()方法。

//猜测一下:release就是将state+上许可数。但是有个疑问,是如何保证没有占用的,不能够release??
//这个地方应该有一定的疑问,毕竟占用的时候,并没有给线程进行标记,那么应该没有办法区别开吧。
//经过自己的验证,发现这一点上,确实有问题。但是你说是问题,也不算是问题。就有点懵
//那么就看一下release()方法
public void release() {
    sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        //之前分析过很多次了,就是唤醒阻塞的线程
        doReleaseShared();
        return true;
    }
    return false;
}
//始终返回true,做的事情就只是state+release的数量
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;
    }
}

4.release(permits)

//完
public void release(int permits) {
    if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值