博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Semaphore源码解析
阅读量:4209 次
发布时间:2019-05-26

本文共 2329 字,大约阅读时间需要 7 分钟。

Semaphore(信号量)是控制访问线程的基于AQS的并发工具。也就是说使用Semaphore能够控制访问资源的并发量。比如在限流这块。

按照限流的逻辑,所以在使用的时候,需要进行设置最大的并发线程,按照我们之前对countDloadLatch的理解。通过设定总量,然后在条件满足之后进行下一工作。

semaphore则是通过设定最大的并发线程,在当前线程消耗的指定的掉总量之后。总量的剩余量与当初设定的总量进行对比,如果小于总量就排队,如果大于总量就进行阻塞。如果超过超时时间就剔除。

semaphore的大致逻辑就是这样。其中使用了AQS做基础的保证。

public class MySemaphore {    public static Semaphore semaphore=new Semaphore(2);    static class task implements Runnable{        @Override        public void run() {            try {                semaphore.acquire();                System.out.println(Thread.currentThread().getName());                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();            }finally {                semaphore.release();            }        }    }    public static void main(String[] args) {        ExecutorService executorService= Executors.newCachedThreadPool();        for (int i=0;i<10;i++){            executorService.submit(new task());        }        executorService.shutdown();    }}

我们可以修改Semaphore的值,然后观察结果,能够很明显的观察到这种并发控制的效果。

下面我们从源码角度看一下他是如何实现的。

从图中可以看出,Seamaphore的结构和其他的并发工具一样,都有公平锁和非公平锁,一版这种情况都是和AQS关系很大,然后看到很多之前我们看到的方法。

下面我们从初始化方法和上述demo的层面上进行深入。

    public Semaphore(int permits) {

        sync = new NonfairSync(permits);

    }

在初始化的时候,默认采用的是非公平锁。

    public Semaphore(int permits, boolean fair) {

        sync = fair ? new FairSync(permits) : new NonfairSync(permits);

    }

或者自行决定是公平还是非公平锁

    public void acquire() throws InterruptedException {

        sync.acquireSharedInterruptibly(1);

    }

当我们调用acquire()方法的时候,发现调用的是acquireSharedInterruptibly,我们跟踪一下。

doAcquireShared这个方法我们之前分析过,就是要从AQS链表中从后向前的寻找。剔除超时的,把能激活的线程向前移动,然后等待之前的额线程执行完毕之后抢夺head节点。

那么这块的意思就是说要先获取state的数量,然后看state减去申请的数量(这里是1),是否还有剩余,如果有剩余说明可以加入到队列。如果state没有剩余,那么就进行自旋,然后一直尝试往链表中添加。

按照这种逻辑,那么释放的时候,就应该是是对state的值进行相加。那么我们看看源码是如何实现的。

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;            }        }

果然,Semaphore就是对state的值进行加法操作。这样保证信号量的值的统一。

好了关于Semaphore的源码解析就到这里了。

总结:

Semaphore使用AQS进行信号量的实现。通过对state值得维护来实现信号量模式,在实际应用中,我们可以采用Semaphore来做系统的限流业务。

转载地址:http://rlkmi.baihongyu.com/

你可能感兴趣的文章
ssh客户端后台运行
查看>>
【React Native】把现代web科技带给移动开发者(一)
查看>>
【GoLang】Web工作方式
查看>>
Launch Sublime Text 3 from the command line
查看>>
【数据库之mysql】mysql的安装(一)
查看>>
【数据库之mysql】 mysql 入门教程(二)
查看>>
【HTML5/CSS/JS】A list of Font Awesome icons and their CSS content values(一)
查看>>
【HTML5/CSS/JS】<br>与<p>标签区别(二)
查看>>
【HTML5/CSS/JS】开发跨平台应用工具的选择(三)
查看>>
【心灵鸡汤】Give it five minutes不要让一个好主意随风而去
查看>>
【React Native】Invariant Violation: Application AwesomeProject has not been registered
查看>>
【ReactNative】真机上无法调试 could not connect to development server
查看>>
【XCode 4.6】常用快捷键 特别是格式化代码ctrl+i
查看>>
【iOS游戏开发】icon那点事 之 实际应用(二)
查看>>
【iOS游戏开发】icon那点事 之 图标设计(三)
查看>>
【IOS游戏开发】之测试发布(Distribution)
查看>>
【IOS游戏开发】之IPA破解原理
查看>>
【一天一道LeetCode】#45. Jump Game II
查看>>
【一天一道LeetCode】#46. Permutations
查看>>
【一天一道LeetCode】#47. Permutations II
查看>>