并发编程原理与实战(四)经典并发协同方式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 "lock" 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,且最多只有一个许可证可以使用,那么可以将这个信号量当成一个互斥的排他锁。这个通常称为二进制信号量,因为它只有两个状态:只有一个许可证可以使用或者零个许可证可以使用。当将信号量当成这种方式使用时,二进制信号量就有了锁可以被其他线程释放的属性(因为信号量没有所有权的概念)。这在某些特殊的场景下非常有用,比如死锁的恢复。

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



