【Java8源码分析】并发包-Semaphore

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72857243


Semaphore是信号量,它的作用是控制多个允许。

打个比方,一个博物馆有容纳1000人的能力(Semaphore的允许是1000),假如1500人同时来参馆,只有1000人能获得允许入馆(获得锁),其余的500则需排队(阻塞),直到馆内的人离开(释放锁)才能放人入馆。


1 如何使用

public class SemaphoreDemo {

    public static void main(String[] args) {
        for (int i = 0; i < 4; i++) {
            new Thread(new SemaphoreTest()).start();
        }

    }

    static class SemaphoreTest implements Runnable{
        public static Semaphore semaphore = new Semaphore(2, true);

        @Override
        public void run() {
            try {
                semaphore.acquire();
                System.out.println(Thread.currentThread() + " getting semaphore");
                Thread.sleep(1000);
                System.out.println(Thread.currentThread() + " realsing semaphore");
                semaphore.release();
            } catch (Exception e) {

            }
        }
    }
}

程序输出

Thread[Thread-1,5,main] getting semaphore
Thread[Thread-0,5,main] getting semaphore
Thread[Thread-0,5,main] realsing semaphore
Thread[Thread-1,5,main] realsing semaphore
Thread[Thread-3,5,main] getting semaphore
Thread[Thread-2,5,main] getting semaphore
Thread[Thread-2,5,main] realsing semaphore
Thread[Thread-3,5,main] realsing semaphore

2 源码分析

Semaphore的内部实现也是基于AQS类的,不了解的可以参考AbstractQueuedSynchronizer同步器一文。

SemaphoreReetrantLock一样有公平锁与非公平锁,ReetrantLock可以看成是Semaphore许可为1的特例,在实现中,Semaphore中的state代表可用的许可,在ReetrantLock中,state大于0代表线程重入的次数

2.1 非公平锁

(1)获取许可

final int nonfairTryAcquireShared(int acquires) {
    for (;;) {
        int available = getState();
        int remaining = available - acquires;
        if (remaining < 0 ||
            compareAndSetState(available, remaining))
            return remaining;
    }
}

remaining表示请求许可后的许可剩余值,如果

  • remaining < 0,许可不足,挂起线程,并且添加线程至排队队列
  • remaining > 0,自旋尝试更新state值,更新成功获得许可

从代码可以看到,当一个线程申请许可时,无需判断是否有线程在排队队列中,体现非公平性

(2)释放许可

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

自旋采用CAS算法更新state状态

2.2 公平锁

(1)获取许可

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

公平锁的机制比非公平锁多了判断排队队列是否为空,如果有其他线程在排队队列中,则该线程也需转入排队队列,体现公平性。


3 总结

  • Semaphore是不可重入的,同一线程多次获取Semaphore是会消耗许可的,例如一个Semaphore的许可为2,同一线程调用了3次acquire函数,该线程会被阻塞

参考

http://www.jianshu.com/p/0090341c6b80


转载请注明出处:http://blog.csdn.net/linxdcn/article/details/72857243

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值