并发编程原理与实战(八)详解并发协同利器Semaphore

并发编程原理与实战(一)精准理解线程的创建和停止

并发编程原理与实战(二)Thread类关键API详解

并发编程原理与实战(三)一步步剖析线程返回值

并发编程原理与实战(四)经典并发协同方式synchronized与wait+notify详解

并发编程原理与实战(五)经典并发协同方式伪唤醒与加锁失效原理揭秘

并发编程原理与实战(六)详解并发协同利器CountDownLatch

并发编程原理与实战(七)详解并发协同利器CyclicBarrier

回顾下CyclicBarrier在多个线程同时调用接口的场景中的使用,如果我们要对接口做并发访问控制,限制同一时间的请求数量,也就是控制调用接口的并发线程数量,防止并发过大造成服务崩溃,“又要并发访问,又不能太猛”,那么要怎么做?Semaphore可以帮助我们实现,本文就来讲解另一个并发协同利器Semaphore。

计数信号量Semaphore

Semaphore的字面意思是信号标,信号灯的意思,java中的专业俗语通常叫信号量。Semaphore 的主要应用场景是通过许可证机制控制多线程对有限资源的并发访问,我们来看看官方说明。

/**
 * A counting semaphore.  Conceptually, a semaphore maintains a set of
 * permits.  Each {@link #acquire} blocks if necessary until a permit is
 * available, and then takes it.  Each {@link #release} adds a permit,
 * potentially releasing a blocking acquirer.
 * However, no actual permit objects are used; the {@code Semaphore} just
 * keeps a count of the number available and acts accordingly.
 *
 * <p>Semaphores are often used to restrict the number of threads than can
 * access some (physical or logical) resource. 
 *
 ...
 */

一个计数的信号量,从概念上讲,信号量维护了一组许可证。每次调用信号量对象的acquire()方法时线程都会进入阻塞状态直到获得许可证,每次调用信号量对象的release()方法时都会添加一个许可证,然后释放一个处于阻塞状态的获得者。Semaphore 通常用在限制访问某些物理资源或者逻辑资源的线程数量。

/** <p>Before obtaining an item each thread must acquire a permit from
 * the semaphore, guaranteeing that an item is available for use. When
 * the thread has finished with the item it is returned back to the
 * pool and a permit is returned to the semaphore, allowing another
 * thread to acquire that item.  Note that no synchronization lock is
 * held when {@link #acquire} is called as that would prevent an item
 * from being returned to the pool.  The semaphore encapsulates the
 * synchronization needed to restrict access to the pool, separately
 * from any synchronization needed to maintain the consistency of the
 * pool itself.
 * */

在获得一项物品之前,每个线程都必须先从信号量中获得一个许可证,以保证那项物品可以使用。当线程使用完物品之后,物品将被返回池中,并且将一个许可证返回给信号量,允许其他线程获得物品。需要注意的是,当线程调用acquire()方法时,并不会持有防止物品被返回给池的锁对象,信号量内部封装了需要限制访问池的同步控制,单独的同步控制以保证池的一致性。

二进制信号量Semaphore

二进制信号量是一种特殊的信号量实现,只有0或1个许可证。

/** <p>A semaphore initialized to one, and which is used such that it
 * only has at most one permit available, can serve as a mutual
 * exclusion lock.  This is more commonly known as a <em>binary
 * semaphore</em>, because it only has two states: one permit
 * available, or zero permits available.  When used in this way, the
 * binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock}
 * implementations), that the &quot;lock&quot; can be released by a
 * thread other than the owner (as semaphores have no notion of
 * ownership).  This can be useful in some specialized contexts, such
 * as deadlock recovery.
 * */

如果一个信号量初始化为1,且最多只有一个许可证可以使用,那么可以将这个信号量当成一个互斥的排他锁。这个通常称为二进制信号量,因为它只有两个状态:只有一个许可证可以使用或者零个许可证可以使用。当将信号量当成这种方式使用时,二进制信号量就有了锁可以被其他线程释放的属性(因为信号量没有所有权的概念)。这在某些特殊的场景下非常有用,比如死锁的恢复。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帧栈

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值