TSemaphore
是具有事务语义的信号量,可用于控制对公共资源的访问。它拥有一定数量的许可证,并且可以获取或释放许可证。
创建一个 TSemaphore
创建一个具有 10 个许可证的 TSemaphore
:
import zio._
import zio.stm._
val tSemaphoreCreate: STM[Nothing, TSemaphore] = TSemaphore.make(10L)
获取一个许可证
一旦外部程序获得许可证,这会减少 TSemaphore
包含的剩余许可证数量。当用户想要访问受限共享资源时,就需要获取可:
import zio._
import zio.stm._
val tSemaphoreAcq: STM[Nothing, TSemaphore] = for {
tSem <- TSemaphore.make(2L)
_ <- tSem.acquire
} yield tSem
tSemaphoreAcq.commit
请注意,如果在信号量中没有剩余的许可证时,尝试获取许可证则具有阻塞的语意,直到有许可证为止。请注意,阻塞语义不会阻塞线程,只当有许可证被释放时系统才会尝试重试 STM 事务。
释放一个许可证
访问完共享资源后,必须释放许可证,以便其它第三方可以访问共享资源:
import zio._
import zio.stm._
val tSemaphoreRelease: STM[Nothing, TSemaphore] = for {
tSem <- TSemaphore.make(1L)
_ <- tSem.acquire
_ <- tSem.release
} yield tSem
tSemaphoreRelease.commit
查询可用的许可证
您可以使用 available
查询在 TSemaphore
中的剩余许可数量:
import zio._
import zio.stm._
val tSemaphoreAvailable: STM[Nothing, Long] = for {
tSem <- TSemaphore.make(2L)
_ <- tSem.acquire
cap <- tSem.available
} yield cap
tSemaphoreAvailable.commit
上面的代码创建一个具有两个许可证的 TSemaphore,然后立刻获得但不释放一个许可。然后,“available
” 将会报告仅剩一个许可证。
执行带有自动获取和释放功能的 STM 操作
您可以将任意在 TSemaphore
上 acquire
和 release
许可证的 STM 操作,作为一个事务的一部分。与其:
import zio._
import zio.stm._
def yourSTMAction: STM[Nothing, Unit] = STM.unit
val tSemaphoreWithoutPermit: STM[Nothing, Unit] =
for {
sem <- TSemaphore.make(1L)
_ <- sem.acquire
a <- yourSTMAction
_ <- sem.release
} yield a
tSemaphoreWithoutPermit.commit
不如:
import zio._
import zio.stm._
val tSemaphoreWithPermit: STM[Nothing, Unit] = for {
sem <- TSemaphore.make(1L)
a <- sem.withPermit(yourSTMAction)
} yield a
tSemaphoreWithPermit.commit
最佳实践是使用 withPermit
而不是直接使用 acquire
和 release
,除非更复杂的,比如涉及多个 STM 动作,并且它们不以 acquire
作为事务的起点,也不以 release
作为终点的情况。
获取和释放多个许可证
使用 acquireN
和 releaseN
一次可以获取和释放若干个许可证:
import zio._
import zio.stm._
val tSemaphoreAcquireNReleaseN: STM[Nothing, Boolean] = for {
sem <- TSemaphore.make(3L)
_ <- sem.acquireN(3L)
cap <- sem.available
_ <- sem.releaseN(3L)
} yield cap == 0
tSemaphoreAcquireNReleaseN.commit