1. 系统要求
iOS 13.0 +
2. 学习路径
1.官方教程-Concurrency
和非Concurrency的异步编程不同,Swift中的asynchronous函数坑可能脱离它正在运行的线程,当第一个函数被阻塞时,另一个asynchronous函数可以在该线程上运行,asynchronous恢复时,执行线程可能不一样
定义和调用异步函数
- 定义一步函数
func listPhotos(inGallery name: String) async -> [String] {
let result = // ... some asynchronous networking code ...
return result
}
- 调用
let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)
使用
Task.sleep(until:tolerance:clock:)
模拟异步操作,便于理解函数执行
异步序列:Asynchronous Sequences
- For-await-in循环
import Foundation
let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
print(line)
}
并发执行asynchronous函数
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
Tasks和Task Groups
Task特性:有层级(结构化并发:structured concurrency)、调度优先级/取消
let group = await withTaskGroup(of: Data.self) { taskGroup in
let photoNames = await listPhotos(inGallery: "Summer Vacation")
for name in photoNames {
taskGroup.addTask { await downloadPhoto(named: name) }
}
}
- Task Group
不要在create创建之外的地方使用,因为add a child task是一个》 mutating(可变)操作, 否则不能保障上下文一致
Group内的task是并行执行的,执行顺序不固定
Group取消操作:1.
cancelAll()
2. task被取消
使用
addTaskUnlessCancelled(priority:body:)
和addTask(priority:body:)
的区别
Task Group的API TaskGroup
非结构化的并发
Task
创建 Task.init(priority:operation:)
和 Task.detached(priority:operation:)
(非current actor)
let newPhoto = // ... some photo data ...
let handle = Task {
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
}
let result = await handle.value
Actors
- 引用类型
actor TemperatureLogger {
let label: String
var measurements: [Int]
private(set) var max: Int
init(label: String, measurement: Int) {
self.label = label
self.measurements = [measurement]
self.max = measurement
}
}
extension TemperatureLogger {
// 已经在actor内运行,所以不需要使用await
func update(with measurement: Int) {
measurements.append(measurement)
if measurement > max {
max = measurement
}
}
}
let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)
- 参与者隔离 actor isolation.
Sendable Types
A type that can be shared from one concurrency domain to another is known as a sendable type. For example, it can be passed as an argument when calling an actor method or be returned as the result of a task
Sendable Type:可以从一个并发域传递给另一个的类型。如:在Actor方法中,参数传递、作为返回值
struct TemperatureReading: Sendable {
var measurement: Int
}
// 和上边的定义等效
//struct TemperatureReading {
// var measurement: Int
//}
extension TemperatureLogger {
func addReading(from reading: TemperatureReading) {
measurements.append(reading.measurement)
}
}
let logger = TemperatureLogger(label: "Tea kettle", measurement: 85)
let reading = TemperatureReading(measurement: 45)
await logger.addReading(from: reading)
2.Concurrency优势和迁移
3.实现原理
Explore structured concurrency in Swift
4.示例代码
5.使用Actor防止数据竞争
Protect mutable state with Swift actors
6.SwiftUI中的应用
Discover concurrency in SwiftUI
7.URL Session中使用
Use async/await with URLSession
8.Swift Concurrency 背后的故事
3.Concurrency和Combine
由于 Swift Concurrency 的推出和大量的 Session 发布,特别是 AsyncSequence 的出现,以及正在路上的 AsyncStream、AsyncThrowingStream 和 continuation 提案(在Xcode 13.0 beta 3 AsyncStream 正式 release ),这些越来越多和 Combine 功能重叠的特性出现在 Swift Concurrency 蓝图里时,大家开始猜测是否 Combine 会被 Swift Concurrency 替代。关于未来是 Swift Concurrency 还是 Combine,我的感觉是,Combine 更侧重在响应式编程上,而响应式编程并不是所有开发人员都会接受的,而 Swift Concurrency 是所有人都愿意接受的开发方式,从 Swift Concurrency 推出后开发者使用的数量和社区反应火热程度来看都比 Combine 要大。在苹果对 Combine 有下一步动作之前,我还是更偏向 Swift Concurrency。 ——《戴铭的开发小册子》