Semaphore浅析

Semaphore 类似于通行证,获取通行证的线程可以执行,未获取的需要等待获取,Semaphore可以用来做资源控制。

	构造函数,默认为非公平模式
 	public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }
    构造函数,公平模式
     public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

acquire

	获取permits个资源
    public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }
    
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
         资源数不足会进入doAcquireSharedInterruptibly方法,分为公平非公平两种
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }
    非公平模式,线程来了直接判断资源够不够,不根据线程先后顺序
     protected int tryAcquireShared(int acquires) {
            return nonfairTryAcquireShared(acquires);
     }
     
     final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
            	获取总资源数
                int available = getState();
          		计算剩余资源数
                int remaining = available - acquires;
                资源不足,返回负数。资源足,cas设置剩余资源数为remaining
                if (remaining < 0 ||  compareAndSetState(available, remaining))
                    return remaining;
            }
      }

      公平模式,判断当前线程队列
       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;
            }
        }
    }
     public final boolean hasQueuedPredecessors() {
        Node h, s;
        if ((h = head) != null) {
        	如果头节点的后继节点是无效线程节点,就从尾到头遍历找到最后一个有效线程节点
            if ((s = h.next) == null || s.waitStatus > 0) {
                s = null; // traverse in case of concurrent cancellation
                for (Node p = tail; p != h && p != null; p = p.prev) {
                    if (p.waitStatus <= 0)
                        s = p;
                }
            }
            判断找到的线程节点是否和当前线程相同,相同返回false,不同返回true,说明有一个更靠前的线程还未执行
            if (s != null && s.thread != Thread.currentThread())
                return true;
        }
        return false;
    }

·············`·``·`··`···················`·········
	 资源数不足时,进入该方法
	 private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        添加线程节点
        final Node node = addWaiter(Node.SHARED);
        try {
            for (;;) {
            	获取前驱线程
                final Node p = node.predecessor();
                前驱为头节点,尝试获取资源
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    大于0,说明资源够,设置新的头节点,回收旧的头节点,唤醒后一个的阻塞线程,
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        return;
                    }
                }
                如果资源不够,当前线程阻塞,等待被唤醒
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } catch (Throwable t) {
            cancelAcquire(node);
            throw t;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值