源码分析-Semaphor

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值