并发编程系列(十一)Semaphore信号量-源码解析

本文深入解析了Semaphore的源码,详细介绍了Semaphore如何基于AbstractQueuedSynchronizer实现并发控制,包括非公平和公平模式下的资源获取与释放过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Semaphore底层是基于AbstractQeuedSynchronizer来实现的所以Semaphore的数据结构也是依托于AQS的数据结构
在这里插入图片描述

1.1 Sync源码解析
    /**
     * 内部类Sync继承自AQS
     */
    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) {
            for (;;) {
                //获取许可
                int available = getState();
                //剩余许可
                int remaining = available - acquires;
                //许可小于0或者CAS设置状态成功
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    //返回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");
                //如果cas成功
                if (compareAndSetState(current, next))
                    //返回true
                    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");
                //cas成功
                if (compareAndSetState(current, next))
                    return;
            }
        }
            //获取并返回所有许可
        final int drainPermits() {
            for (;;) {
                //获取许可数
                int current = getState();
                //如果current等于0或者cas成功
                if (current == 0 || compareAndSetState(current, 0))
                    return current;
            }
        }
    }
1.2 NonfairSync源码解析

NonfairSync类继承自Sync类,表示采用非公平策略获取资源,其中有一个tryAcquireShared方法,重写AQS的tryAcquireShared方法:

    /**
     * 非公平版本
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -2694183684443567898L;
 
        NonfairSync(int permits) {
            super(permits);
        }
        //共享模式下获取资源
        protected int tryAcquireShared(int acquires) {
            //调用父类Sync中的NonfairSyncTryAcquireShared方法
            return nonfairTryAcquireShared(acquires);
        }
    }
1.3 FairSync 源码解析

FairSync 类继承了Sync类,表示采用公平策略获取资源,其中只有一个tryAcquireShared方法,重写了AQS的tryAcquireShared:

    static final class FairSync extends Sync {
        private static final long serialVersionUID = 2014338818796000944L;
 
        FairSync(int permits) {
            super(permits);
        }
        //共享模式下获取资源
        protected int tryAcquireShared(int acquires) {
            for (;;) {
                //同步队列存在比当前线程等待更久的结点
                //如果存在则返回-1
                if (hasQueuedPredecessors())
                    return -1;
                //获取state状态
                int available = getState();
                //剩余时间
                int remaining = available - acquires;
                //如果剩余许可小于0或者cas成功
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }
    }

Semaphore类的非公平模式获取许可源码解析

    public void acquire() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
 
    public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }

acquire调用父类AQS中的AcquireSharedinterruptbly方法

   public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        //如果线程被中断
        if (Thread.interrupted())
            throw new InterruptedException();
        //tryAcquireShared方法需要子类实现
        //如果tryAcquireShared方法返回小于0
        //则获取资源失败
        if (tryAcquireShared(arg) < 0)
            //调用doAcquireSharedInterruptibly方法
            doAcquireSharedInterruptibly(arg);
    }

AcquireSharedinterruptbly方法调用的tryAcquireShared方法在非公平模式下的实现如下

    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

tryAcquireShared方法调用的NonfairTryAcquireShared方法如下:详细参考: Sync源码解析

     final int nonfairTryAcquireShared(int acquires) {
            for (;;) {
                int available = getState();
                int remaining = available - acquires;
                if (remaining < 0 ||
                    compareAndSetState(available, remaining))
                    return remaining;
            }
        }

tryAcquireShared方法返回小于0,则获取资源失败,执行doAcquireSharedInterruptibly方法

    private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

非公平模式释放许可资源源码解析
释放许可

  public void release() {
        sync.releaseShared(1);
    }
    public void release(int permits) {
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
    }

release方法调用AQS中的releaseShared方法

    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

其中tryReleaseShared需要子类实现

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

如果tryReleaseShared返回true将执行都releaseShared方法

   private void doReleaseShared() {
 
        for (;;) {
            Node h = head;
            if (h != null && h != tail) {
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                        continue;            // loop to recheck cases
                    unparkSuccessor(h);
                }
                else if (ws == 0 &&
                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue;                // loop on failed CAS
            }
            if (h == head)                   // loop if head changed
                break;
        }
    }

公平模式获取许可源码分析

公平模式获取许可的acquire方法与非公平模式下获取许可是一样的,不同的是tryAcquireShared方法的实现;与非公平模式相比,公平模式多了hasQueuedPredecessors。

        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() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

公平模式释放许可和非公平模式是一样的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值