onm*_*133 0 actor async-await swift swift-concurrency
我正在观看有关使用 Swift Actor 保护可变状态的WWDC 视频
在一个示例中,他们展示了如何同时调用参与者方法
想象一下,我们有两个不同的并发任务试图同时获取相同的图像。第一个发现没有缓存条目,开始从服务器下载图像,然后被挂起,因为下载需要一段时间。当第一个任务是下载映像时,新映像可能会部署到同一 URL 下的服务器。现在,第二个并发任务尝试获取该 URL 下的图像。它还看不到缓存条目,因为第一次下载尚未完成,然后开始图像的第二次下载。下载完成时它也会被暂停。一段时间后,其中一个下载(假设这是第一个下载)将完成,并且其任务将在 Actor 上恢复执行。它填充缓存并返回猫的结果图像。现在第二个任务已完成下载,因此它被唤醒。它用它得到的悲伤猫的图像覆盖缓存中的相同条目。因此,即使缓存中已经填充了图像,我们现在也会为同一 URL 获取不同的图像。
Actor 的整个想法不就是确保在任何给定时间只有一个调用者可以直接与 Actor 交互吗?
这是我的例子。在这里您可以看到“BEGIN增量”后面始终跟着“END增量”,并且后续调用increment必须等待
actor Counter {
var count = 1
func increment() {
print("BEGIN increment")
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
let string = String(data: data, encoding: .utf8) ?? ""
print("END increment")
count += 1
}
}
struct ContentView: View {
@State var counter = Counter()
var body: some View {
Button {
Task.detached {
await counter.increment()
}
} label: {
Text("Click")
}
}
}
Run Code Online (Sandbox Code Playgroud)
视频中的问题是 actor 函数是异步的(一个async方法),await其中包含一个。Actor 保证一次只有一个 Actor 的同步函数运行。
苹果的警告是关于async向你的 Actor 添加方法。一个await在一个async是一个明确的指示符,表明您愿意让系统挂起当前线程并放弃参与者的上下文。这可以允许另一个任务声明该上下文并“重新输入”该函数。
这也意味着您在 之前得出的有关参与者状态的任何结论await在 之后的代码中都不能被认为是正确的await。
在您的示例中,您的increment函数是同步的(未标记async)。因此,在您的函数中,没有必要暂停参与者上下文,从而允许另一个线程声明它。
换句话说,参与者的保证是使用 Swift Concurrency 实现的。async如果您使用 Swift Concurrency在 Actor 上实现方法,您可能会破坏这些保证,并打开一个可能会出现问题的裂缝。
| 归档时间: |
|
| 查看次数: |
336 次 |
| 最近记录: |