Swift 并发中的锁
这个包暴露了两个类型:AsyncLock
和 AsyncRecursiveLock
。它们允许你定义异步临界区。一次只有一个任务可以进入临界区。与传统的锁不同,你可以在持有这些锁的同时安全地进行异步调用。
这是一个处理 Actor 重入的方便工具。
你可能会觉得有用的其他并发包包括 Queue 和 Semaphore。
Swift 包管理器
dependencies: [
.package(url: "https://github.com/mattmassicotte/Lock", branch: "main")
]
这些锁是不可发送(non-Sendable)的。这是一个刻意的选择,不允许跨隔离域共享锁。如果你想这样做,首先要认真思考为什么,然后查看 Semaphore。
请注意,尝试获取一个已经被锁定的 AsyncLock
将会导致你的 Actor 死锁。
import Lock
actor MyActor {
var value = 42
let lock = AsyncLock()
let recursiveLock = AsyncRecursiveLock()
func hasCriticalSections() async {
// no matter how many tasks call this method,
// only one will be able to execute at a time
await lock.lock()
self.value = await otherObject.getValue()
lock.unlock()
}
func hasCriticalSectionsBlock() async {
await recursiveLock.withLock {
// acquiring this multiple times within the same task is safe
await recursiveLock.withLock {
self.value = await otherObject.getValue()
}
}
}
}
不幸的是,我还没有完全弄清楚如何正确地实现 AsyncRecursiveLock
,所以它目前不是公开的。
我很乐意听取你的意见!提交 Issue 或 Pull Request 都是很好的方式。 Matrix 空间 和 Discord 也可用于实时帮助,但我强烈倾向于以文档的形式回答问题。
我更喜欢协作,如果你有类似的项目,我很乐意找到合作的方式。
我更喜欢使用制表符进行缩进,以提高可访问性。 但是,我宁愿你使用你喜欢的系统并提交 PR,而不是因为空格而犹豫不决。
通过参与此项目,您同意遵守 贡献者行为准则。