信号量 Semaphore
数据类型,它允许通过 withPermit 方法在纤程之间进行同步,该方法可以安全地获取和释放许可证。信号量是基于 Ref[A]
数据类型的。
操作
例如,异步任务可以通过获取和释放具有给定数量许可的信号量来完成彼此的同步。当信号量中的许可值不足,获取操作无法执行时,该任务将在纤程队列中被置于挂起状态,直到有足够的许可值时被唤醒:
import java.util.concurrent.TimeUnit
import zio._
import zio.console._
import zio.duration.Duration
val task = for {
_ <- putStrLn("start")
_ <- ZIO.sleep(Duration(2, TimeUnit.SECONDS))
_ <- putStrLn("end")
} yield ()
val semTask = (sem: Semaphore) => for {
_ <- sem.withPermit(task)
} yield ()
val semTaskSeq = (sem: Semaphore) => (1 to 3).map(_ => semTask(sem))
val program = for {
sem <- Semaphore.make(permits = 1)
seq <- ZIO.effectTotal(semTaskSeq(sem))
_ <- ZIO.collectAllPar(seq)
} yield ()
(以上)二值信号量只是一种特殊的信号量。我们可以要求获取和释放任意指定数量的信号量:
val semTaskN = (sem: Semaphore) => for {
_ <- sem.withPermits(5)(task)
} yield ()
withPermit(及其对应的计数版本 withPermits)的保证是,无论任务是成功,失败还是被中断,许可证在被成功获取之后都会被释放。