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

来源:互联网 发布:种子结构网络教研总结 编辑:程序博客网 时间:2024/05/14 06:15

转载请注明出处: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 semaphoreThread[Thread-0,5,main] getting semaphoreThread[Thread-0,5,main] realsing semaphoreThread[Thread-1,5,main] realsing semaphoreThread[Thread-3,5,main] getting semaphoreThread[Thread-2,5,main] getting semaphoreThread[Thread-2,5,main] realsing semaphoreThread[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

原创粉丝点击