首页 > 编程知识 正文

semaphore是什么,许可证服务器

时间:2023-05-03 12:13:18 阅读:50837 作者:1033

目录

Semaphore许可证

Semaphore原理分析

Semaphore方法总结

Semaphore总结

Semaphore许可证Semaphore是一种线程同步工具,主要用于同时允许一定数量的线程并行操作共享资源的场景。

Semaphore可用于限制用户数相似的场景,如停车场和高峰酒店位置。

首先,举个例子看看它的使用方法。

publicstaticvoidmain (字符串[ ] args )//10个finalintpermits=10;//定义10个Semaphore许可证的finalsemaphoresemaphore=new semaphore (permits,true ); //20个线程的intstream.range (0,20 ).foreach I-{ new thread } )-{ boolean flag=semaphore.try acquire } ); if(flag ) (system.out.println ) Thread.currentThread ) (.getName )、“许可证获取”); } else { system.out.println (thread.current thread ().getName )“未获得许可”}try{//许可后模拟业务处理}finally{semaphore.release (; system.out.println (thread.current thread ().getName )“发布许可证”); },'线程-' i ).start ); ); }私密性staticvoidsleep ((try ) timeunit.seconds.sleep ) newrandom ).nextInt(3) )3); } catch (互联互通) {e.printStackTrace ); }在上述代码中,我们创建了10个许可证,并选中了复选框。 这意味着最多有10个线程同时运行。

Semaphore对象的许可数量和许可方式根据参与结构制定了公平的方式。

tryAcquire ()是一种获取不阻止线程、获取许可证并返回true、无法获取并返回false的许可证的方法。

release ) )获得许可证的线程必须在运行结束后释放许可证。 为了保证许可证的释放(release ) )方法通常写在finally语句块中。

Semaphore原理分析Semaphore的实现原理是什么? 接下来和复选标记一起看源代码吧。

Semaphore是基于AQS共享模型的实现,其维护的内部类实现了AbstractQueuedSynchronizer。

在Semaphore中,state表示许可证计数,因为Semaphore在构建时指定许可证计数是用于指定AQS同步器状态状态的值。

也可以指定在构建Semaphore时获取许可的公平或不公平方法,默认值为不公平获取方法。

Semaphore重写以共享模式许可的tryAcquireShared ()和释放许可的tryReleaseShared ) )方法,其中内部类的NonfairSync和FairSync不同

内部类Sync源代码的注释如下:

abstractstaticclassyncextendsabstractqueuedsynchronizer { privatestaticfinallongserialversionuid=1}

192457210091910933L; //有参构造,permits即是state的值    Sync(int permits) {        setState(permits);    } //获取许可证数量,即获取state同步器状态值    final int getPermits() {        return getState();    } //非公平方式获取操作    final int nonfairTryAcquireShared(int acquires) {        for (;;) {            //获取剩余许可证数量            int available = getState();            //将剩余许可证减去当前线程想要获取的许可证数量            int remaining = available - acquires;            //如果小于0,则返回剩余的许可证数量,是个负值            //如果不小于0,则通过CAS修改state的值,修改成功则返回剩余数量,是个正值            //如果CAS失败,则一直循环            if (remaining < 0 ||                compareAndSetState(available, remaining))                return remaining;        }    } //共享方式释放操作    protected final boolean tryReleaseShared(int releases) {        for (;;) {            //获取state的值            int current = getState();            //将state的值加上当前线程要释放的许可数量            int next = current + releases;            //如果释放之后的许可数量小于当前数量,则抛异常            if (next < current) // overflow                throw new Error("Maximum permit count exceeded");            //cas修改state的值,修改成功返回true,失败返回false            if (compareAndSetState(current, next))                return true;        }    }}

NonfairSync非公平类,其获取许可的操作直接调用了父类Sync的nonfairTryAcquireShared()方法。

/** * NonFair version */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公平类,其自己实现了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;            //如果是下一个要唤醒的节点,则尝试获取许可            int available = getState();            int remaining = available - acquires;            if (remaining < 0 ||                compareAndSetState(available, remaining))                return remaining;        }    }}

我们之前《AQS之共享模式》一文中学习了AQS共享模式的原理,我们了解到tryAcquireShared()方法返回小于0的数值则表示线程获取许可失败,返回大于0的数值则表示线程许可成功。

获取失败之后会怎么样呢?

《AQS之共享模式》给你答案喔!

Semaphore基本流程:

Semaphore方法总结

Semaphore构造器

Semaphore(int permits):定义Semaphore指定许可数量,并且默认非公平的方式获取许可。

Semaphore(int permits, boolean fair):定义Semaphore指定许可数量以及同步方式。

获取方法

acquire():当前线程调用此方法获取许可证,获取不到会进入阻塞状态一直等待,直到Semaphore有可用的许可或者被其他线程打断。如果Semaphore有可用的许可,该方法会立即返回。

acquire(int permits):当前线程调用该方法会向Semaphore获取指定permits的许可数量,permits不能小于0。该方法作用与acquire()一样,只是指定了获取的许可数量,acquire()是获取一个许可数量。

acquireUninterruptibly():当前线程调用此方法获取许可,如果获取不到会一直阻塞而且不能被打断,直到Semaphore有可用许可才能退出阻塞。此方法一般不用,因为可能会导致大规模的线程阻塞而导致Java进程假死现象。

acquireUninterruptibly(int permits):该方法与acquireUninterruptibly()作用一样,只是可以指定获取permits个许可数量,permits不能小于0。

tryAcquire():尝试获取许可数量,只会向Semaphore申请一个许可数量,如果Semaphore的许可数量大于等于1,将会获取成功返回true,否则将会获取许可失败返回false。

tryAcquire(long timeout, TimeUnit unit):尝试获取许可数量,也是只申请一个许可,但是它增加了超时参数。如果在超时的时间内还是没有可用的许可,当前线程会进入阻塞状态,直到达到超时时间或者超时时间内获得了许可,或者阻塞线程被其他线程打断。

tryAcquire(int permits):该方法与tryAcquire()作用一样,只是可以指定获取permits个许可数量,permits不能小于0。

tryAcquire(int permits, long timeout, TimeUnit unit):该方法可以获取permits个许可数量,并且可以设置超时时间。

释放操作

release():释放一个许可证,Semaphore内部的许可证数量会加1,表示多了1个可用的许可。

release(int permits):释放permits个许可证,Semaphore内部的许可证数量会加permits。permits不能小于0。

 

Semaphore总结

Semaphore可以允许一定数量的线程对共享资源进行访问,并且提供了丰富的获取操作:阻塞或者不阻塞,中断或者不中断、获取多个许可或者一个许可。

Semaphore虽然可以控制并发的线程数量,但是对共享资源的数据安全并没有提供任何保证,所以如果涉及到了共享可变资源的并发需要额外的控制。

如果在开发中使用了不阻塞的方式获取许可数量,需对返回结果进行处理,否则可能出现尝试获取许可失败却依然执行了业务逻辑。

好了今天就到这里,祝福大家周末愉快 !!!

下一篇文章是最后一个JUC工具类Phaser,哇哇哇,看到光明了!!!

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。