groue_Semaphore 0.0.8

groue_Semaphore 0.0.8

Levi Bostian 维护。



  • Gwendal Roué

信号量

Swift 并发的一个同步原语

要求: iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ • Swift 5.7+ / Xcode 14+

📖 文档


此包提供了 AsyncSemaphore,这是一个传统的计数值信号量。

DispatchSemaphore 不同,它不会阻塞任何线程。相反,Swift 并发任务会被挂起“等待”信号量。

用法

您可以使用信号量暂停任务并在稍后再恢复它

let semaphore = AsyncSemaphore(value: 0)

Task {
  // Suspends the task until a signal occurs.
  await semaphore.wait()
  await doSomething()
}

// Resumes the suspended task.
semaphore.signal()

一个 actor 可以使用信号量,使得它的方法不能并发执行,避免“actor 可递归进入”问题

actor MyActor {
  private let semaphore = AsyncSemaphore(value: 1)
  
  func serializedMethod() async {
    // Makes sure no two tasks can execute
    // serializedMethod() concurrently. 
    await semaphore.wait()
    defer { semaphore.signal() }
    
    await doSomething()
    await doSomethingElse()
  }
}

信号量通常可以限制对资源的并发访问数量

class Downloader {
  private let semaphore: AsyncSemaphore

  /// Creates a Downloader that can run at most
  /// `maxDownloadCount` concurrent downloads. 
  init(maxDownloadCount: Int) {
    semaphore = AsyncSemaphore(value: maxDownloadCount) 
  }

  func download(...) async throws -> Data {
    try await semaphore.waitUnlessCancelled()
    defer { semaphore.signal() }
    return try await ...
  }
}

您可以在最新的示例中看到,wait() 方法有一个 waitUnlessCancelled 变体,如果任务在发出信号之前被取消,则会抛出 CancellationError

有关信号量的妙用,请参阅 Swift 中信号量的美感 🚦。这篇文章讨论了 DispatchSemaphore,但它可以很容易地移植到 Swift 并发:从上述示例中获得灵感。