Semaphore-信号量的实现分析

Semaphore
Semaphore 信号量:可以用来控制同时访问特定资源的线程数量;通过协调各个线程以保证合理的使用公共资源
构造

// permits 设置许可证的数量
public Semaphore(int permits) {
    // 默认非公平
    sync = new NonfairSync(permits);
}
// permits 设置许可数量
// fair 设置是否采用公平模式
public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

非公平模式
acquire()
获取许可。只有当获取到可用的许可,或者当前线程被中断;否则该线程被阻塞

public void acquire() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}

默认会调用 NonfairSync 下的 tryAcquireShared 方法,继续调用父类的 nonfairTryAcquireShared 方法

protected int tryAcquireShared(int acquires) {
    return nonfairTryAcquireShared(acquires);
}

final int nonfairTryAcquireShared(int acquires) {
    for (;;) {
        // 获取当前 state 值
        // 也即是当前可用的许可数
        int available = getState();
        // 当前可用许可数减去尝试获取许可的数
        // 得到剩余许可数
        int remaining = available - acquires;
        // remaining < 0 说明当前可用许可数小于尝试获取许可数,也即是获取同步状态失败 直接返回 remaining, 退出循环 当前线程会被添加到同步队列中
        // remaining > 0 说明当前可用许可数大于尝试获取许可数,
        // 则执行 compareAndSetState 更新 state , 若更新成功则返回 退出循环 当前线程获取到许可
        // 若 compareAndSetState 更新失败,说明有其他线程获取到许可,则继续轮询
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

release
释放许可

public void release() {
    sync.releaseShared(1);
}

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");
        // 更新 state 值, 更新成功则返回 true 退出循环;并唤醒同步队列上阻塞的线程
        // 更新 state 值失败,说明有其他线程获取许可或释放了许可,则继续轮询
        if (compareAndSetState(current, next))
            return true;
    }
}

公平模式
acquire
公平模式下获取许可

protected int tryAcquireShared(int acquires) {
    for (;;) {
        // 判断同步队列上是否有阻塞的线程
        // 若有的话,返回 -1 表示获取许可失败 退出循环加入同步队列中
        if (hasQueuedPredecessors())
            return -1;
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

从上述代码中可以看到,公平模式下获取许可和非公平模式下基本类似,只是为了保证 FIFO ,添加了 hasQueuedPredecessors 判断限制。

release
公平模式下与非公平模式一样

小结
Semaphore 可以用来实现限流的作用。
最后,如果你跟我一样都喜欢java,也在学习java的道路上奔跑,欢迎你添加 V X sweetbest130 每天都会分享java最新业内资料,共同交流学习,让学习变(编)成(程)一种习惯!
扫描二维码获取资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值