源码分析-Semaphor

来源:互联网 发布:汽配个性淘宝店名大全 编辑:程序博客网 时间:2024/06/16 07:24

semaphore

java中的Semaphore主要用来限制线程的数量。而不是用来限制资源的访问。Semaphore所拥有的集是非常抽象的集合。所以说Semaphore在获取和是否的过程中不会持有特定对象的锁。

即使排除java的语义概念,锁和信号量,虽然都是基于等待唤醒机制,但是也是不同的同步组件。虽然锁可以用来做同步器,同步器可以用来做锁,但是信号量并没有所有者的概念。由于没有所有者的概念,信号量一般用来限制线程数量,而锁用来控制资源访问。这样有什么好处,一个例子就是在死锁恢复的过程中,如果你用的是锁,那必须又拥有这个锁的拥有者去释放,如果你用的是信号量就不需要拥有者去释放这个线程。比如你可以设定在线程终止时自动释放。这样就不会绑定特定的拥有者。

主要方法

从结构上说Semaphore的构成比较简单,就是内部有三个类,一个Sync继承自AQS。这个Sync是一个抽象类,下面继承了2个类分别是NonfairSync和FairSync两个具体的子类,在构造的时候选择使用哪一个。
只要搞懂AQS,Semaphore的内容很简单。
Semaphore的方法基本上没有什么可以说的,这里就看一下这三个类的主要方法就可以了:

Sync

    abstract static class Sync extends AbstractQueuedSynchronizer {        private static final long serialVersionUID = 1192457210091910933L;        Sync(int permits) {            setState(permits);        }        final int getPermits() {            return getState();        }        final int nonfairTryAcquireShared(int acquires) {//这里主要是非公平锁的实现方式,但是我有一点不太明白为什么要写在Sync并且用final,如果我来写的话我会放在NonfairTryAcquireShared中间。这个也是通常实现获取非公平共享锁的典型形式。            for (;;) {                int available = getState();                int remaining = available - acquires;                if (remaining < 0 ||                    compareAndSetState(available, remaining))                    return remaining;            }        }        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;            }        }        final void reducePermits(int reductions) {//这个方法主要是控制运行线程数量的。            for (;;) {                int current = getState();                int next = current - reductions;                if (next > current) // underflow                    throw new Error("Permit count underflow");                if (compareAndSetState(current, next))                    return;            }        }        final int drainPermits() {            for (;;) {                int current = getState();                if (current == 0 || compareAndSetState(current, 0))                    return current;            }        }    }

NonfairSync

非公平锁的实现比较简单只要委托给tryAcquireShared就行

    static final class NonfairSync extends Sync {        private static final long serialVersionUID = -2694183684443567898L;        NonfairSync(int permits) {            super(permits);        }        protected int tryAcquireShared(int acquires) {            return nonfairTryAcquireShared(acquires);        }    }

FairSync

公平锁的实现

    static final class FairSync extends Sync {        private static final long serialVersionUID = 2014338818796000944L;        FairSync(int permits) {            super(permits);        }        protected int tryAcquireShared(int acquires) {            for (;;) {                if (hasQueuedPredecessors())//和非公平锁的实现的区别就是这里加了这一条这个是AQS的方法用来判断当前是否有线程排队获取锁。其他内容和非公平锁一致。                    return -1;                int available = getState();                int remaining = available - acquires;                if (remaining < 0 ||                    compareAndSetState(available, remaining))                    return remaining;            }        }    }
0 0
原创粉丝点击