JUC--Semaphore源码分析(基于JDK1.8)

1 概述

通过前面(参考JUC– Semaphore学习(一)简介和使用 )对Semaphore的介绍,我们对Semaphore有了一个基本的认识,我们知道Semaphore通常用于限制对资源使用的线程数量,现在就要针对Semaphore的源码进行分析,Semaphore的结构如下:

《JUC--Semaphore源码分析(基于JDK1.8)》

从上图我们可以发现,这里又出现了AQS的身影,我们可以看出AQS的重要性。所以再学习JUC的时候非常有必要对AQS的源码有个深入学习。并且这里有公平和非公平两种实现方式。我们接下来会分析是如何实现的。

2 属性

    private final Sync sync;

至此我们可以猜想Semaphore的功能实现主要是依靠Sync来实现的,而通过之前对AQS的学习我们知道针对AQS的设计使用了模板方法模式,所以不难想到,这里的Sync里面实现的就是模板方法模式中的基本方法。

3 构造函数

(1)创建指定数量的信号量,默认为非公平模式。

 public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

(2)创建指定数量的信号量,根据指定的公平模式选择同步机制。

public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

4 具体方法分析

我们知道针对Semaphore中锁的获取有公平和非公平模式,所以我们这里就针对这两种模式来分别分析两个核心的方法的实现。

4.1 非公平模式(NonfairSync)

acquire()

前面我们已经分析了CountDownLatch和CyclicBarrier的源码。对AQS家族有了个深入的认识。所有在这个地方我们不再分析整个函数的调用链了,直接来查看比较关键的基本函数tryAcquireShared。

直接上源码加注释分析。

protected int tryAcquireShared(int acquires) {

    //这里直接调用基类的nonfairTryAcquireShared函数
    return nonfairTryAcquireShared(acquires);
}

从上面我们可以看出,这里非公平模式下tryAcquireShared函数事依赖于基类的nonfairTryAcquireShared函数。

final int nonfairTryAcquireShared(int acquires) {
    for (;;) {

       //获取可用许可
       int available = getState();

       //计算得到当前剩下的可用许可
       int remaining = available - acquires;
       if (remaining < 0 ||

           //使用CAS设置可用许可
           compareAndSetState(available, remaining))
           return remaining;
    }
}

从上面我们可以看出这里其实就是在操作构造函数的初始许可值,只有当余下许可大于0的情况,线程才能得以继续执行。

4.2 公平模式

acquire()

上面我们分析了非公平模式,下面我们来看看公平模式到底是咋个保证公平的呢。

protected int tryAcquireShared(int acquires) {
    for (;;) {

        //通过这里来保证公平性,针对这个函数的分析可以查看前面的文章
        if (hasQueuedPredecessors())
            return -1;
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

4.3 释放锁

上面我们针对公平模式和非公平模式分析了锁的获取,由于锁的释放都使用了相同的函数,所以在这个地方我们直接分析锁的释放tryReleaseShared函数。

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");

        //使用CAS设置许可
        if (compareAndSetState(current, next))
            return true;
    }
}

上面就是针对Semaphore的源码分析,欢迎大家交流或指正。

    原文作者:JUC
    原文地址: https://blog.csdn.net/ONROAD0612/article/details/82492784
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞