jdk源码解析四之Semaphore

Semaphore

计数信号量:控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,实现某种资源池,对容器施加边界

acquire

步骤同CountDownLatch.wait

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

        protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
        }
        final int nonfairTryAcquireShared(int acquires) {
        //<0才阻塞
            for (;;) {
                //获取同步状态的值。
                int available = getState();
                int remaining = available - acquires;
                //available为0或者更新成功,直接返回
                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;
                //内存溢出,也就是超过了Integer范围上限
                if (next < current) // overflow
                    throw new Error("Maximum permit count exceeded");
                //修改值返回
                if (compareAndSetState(current, next))
                    return true;
            }
        }

总结

与闭锁和其类似,闭锁是为0,才可以访问,信号量恰恰相反,
信号量和闭锁的区别是不是一次性的,可以重复限定多少线程可以访问资源.
如果不限定释放的条件,可以不停的释放从而超过构造设置的许可个数,
建议这样使用

   public boolean add(T o) throws InterruptedException {
        //阻塞获得许可
        sem.acquire();
        boolean wasAdded = false;
        try {
            wasAdded = set.add(o);
            return wasAdded;
        } finally {
            //返回许可给信号量
            if (!wasAdded)
                sem.release();
        }
    }

    public boolean remove(Object o) {
        boolean wasRemoved = set.remove(o);
        if (wasRemoved)
            sem.release();
        return wasRemoved;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章