zoukankan      html  css  js  c++  java
  • 《java.util.concurrent 包源码阅读》17 信号量 Semaphore

    学过操作系统的朋友都知道信号量,在java.util.concurrent包中也有一个关于信号量的实现:Semaphore。

    从代码实现的角度来说,信号量与锁很类似,可以看成是一个有限的共享锁,即只能被有限数量的线程使用的共享锁。

    因为存在计数,因此Semaphore的构造函数有参数permits来设定计数:

        public Semaphore(int permits) {
            sync = new NonfairSync(permits);
        }

    涉及到线程排队等待的问题,Semaphore也支持fair和unfair模式:

        public Semaphore(int permits, boolean fair) {
            sync = fair ? new FairSync(permits) : new NonfairSync(permits);
        }

    说到线程排队,前面在说“锁”的时候讲过AbstractQueuedSynchronizer,它实现了类似获取锁失败,管理等待的线程的功能。因此信号量的实现同样需要借助这个类。

    abstract static class Sync extends AbstractQueuedSynchronizer
    
    // Unfair模式的实现
    static final class NonfairSync extends Sync
    
    // Fair模式的实现
    static final class FairSync extends Sync

    Sync类使用AbstractQueuedSynchronizer的state来存储信号量的计数:

            Sync(int permits) {
                setState(permits);
            }

    因为信号量与共享锁类似,因此在获取资源和释放资源的时候使用的都是AbstractQueuedSynchronizer的shared类型的方法。

    再次回到前面的unfair和fair模式,这种所谓的公平体现在获取锁的时候:unfair是后来先得,fair是先来先得。来看两者的尝试获取资源的方法:

            // unfair模式
            final int nonfairTryAcquireShared(int acquires) {
                // 直接检查是不是有资源,根本不看前面有没有其他排队的
                for (;;) {
                    int available = getState();
                    int remaining = available - acquires;
                    if (remaining < 0 ||
                        compareAndSetState(available, remaining))
                        return remaining;
                }
            }
    
            // fair模式
            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;
                }
            }

    对于信号量来说,获取资源的过程,就是一个更新资源计数的过程。对于释放资源来说,也是一样。

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

    关于信号量的实现,有了AbstractQueuedSynchronizer和锁的基础,是非常好理解的。

  • 相关阅读:
    add to svn ignore disabled
    Zend 安装 OpenExplorer插件
    Win7系统怎么清理注册表残留?【系统天地】
    永久免费Win10企业版激活密钥大全【系统天地】
    Win7取消自动锁屏的方法步骤【系统天地】
    手把手教你怎么激活windows10专业版【系统天地】
    win8解除网速限制的操作方法【系统天地】
    教你win10系统显卡驱动安装失败的解决方法【系统天地】
    Win7移动硬盘在电脑上不显示怎么办【系统天地】
    Win10运行程序提示不受信任的解决方法【系统天地】
  • 原文地址:https://www.cnblogs.com/wanly3643/p/3937394.html
Copyright © 2011-2022 走看看