自 Swift 5.5 起,Swift 引入了强大的原生并发模型,基于 Structured Concurrency(结构化并发) 和 Actor 模型,极大提升了异步代码的可读性和安全性。
🔑 1. Swift 并发的核心组件
#
组件 | 作用 | 关键词 |
---|
async / await | 异步函数的定义与调用,简化回调地狱 | async 、await |
Task | 创建异步任务,支持并发执行 | Task {} |
TaskGroup / withTaskGroup | 并发任务组,批量任务的并发控制 | withTaskGroup |
Actor | 保证数据访问的线程安全,避免竞争条件 | actor |
@MainActor | 强制代码在主线程执行,适用于 UI 更新 | @MainActor |
DetachedTask | 脱离父任务的异步任务,适合独立后台任务 | DetachedTask {} |
AsyncSequence | 异步数据流处理,适合流式数据和事件监听 | for await in |
Continuation | 与传统回调机制互操作,支持逃逸闭包转换成异步调用 | CheckedContinuation |
Sendable | 标记类型在并发环境中是线程安全的 | @Sendable |
🌟 2. async
/ await
:现代异步的基石
#
✅ 基础用法:
#
func fetchData() async -> String {
// 模拟异步网络请求
try? await Task.sleep(nanoseconds: 1_000_000_000)
return "数据加载完成"
}
Task {
let data = await fetchData()
print(data) // 输出:数据加载完成
}
async
:声明异步函数。await
:等待异步操作完成,不阻塞线程,代码仍然顺序执行。
⚡ 3. Task
:轻量级并发任务
#
🚀 创建任务:
#
Task {
let result = await fetchData()
print(result)
}
🚀 取消任务:
#
let task = Task {
try Task.checkCancellation()
return await fetchData()
}
task.cancel() // 主动取消任务
Task
会自动继承当前上下文(如优先级、Actor 等)。- 支持任务的 取消(Cancellation) 和 优先级(Priority) 控制。
🤹♂️ 4. TaskGroup
:并发任务组合
#
✅ 并发处理多个任务:
#
func loadMultipleData() async {
await withTaskGroup(of: String.self) { group in
for i in 1...3 {
group.addTask {
try? await Task.sleep(nanoseconds: UInt64(i) * 1_000_000_000)
return "任务 \(i) 完成"
}
}
for await result in group {
print(result)
}
}
}
Task {
await loadMultipleData()
}
- 自动管理任务的生命周期,避免资源泄漏。
- 支持异步
for-await-in
遍历结果。
🧵 5. Actor
:解决数据竞争的利器
#
✅ 定义 Actor:
#
actor Counter {
private var value = 0
func increment() {
value += 1
}
func getValue() -> Int {
return value
}
}
let counter = Counter()
Task {
await counter.increment()
print(await counter.getValue()) // 输出:1
}
actor
保证 内部状态的线程安全,无需加锁。- 数据访问需要使用
await
,确保串行化执行。
🎯 6. @MainActor
:确保 UI 线程安全
#
@MainActor
class ViewModel: ObservableObject {
@Published var message = "初始值"
func updateMessage() {
message = "更新后的值"
}
}
Task {
let vm = ViewModel()
await vm.updateMessage() // 自动切换到主线程
}
- 适用于 SwiftUI 或 UIKit 中的 UI 更新,防止线程冲突。
🌊 7. AsyncSequence
:处理异步数据流
#
✅ 异步流示例:
#
struct NumberStream: AsyncSequence {
typealias Element = Int
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator()
}
struct AsyncIterator: AsyncIteratorProtocol {
private var current = 0
mutating func next() async -> Int? {
try? await Task.sleep(nanoseconds: 1_000_000_000)
current += 1
return current <= 5 ? current : nil
}
}
}
Task {
for await number in NumberStream() {
print(number) // 输出 1, 2, 3, 4, 5
}
}
🔄 8. Continuation
:兼容旧版回调
#
✅ 将回调封装成异步:
#
func legacyAPI(completion: @escaping (String) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion("传统 API 数据")
}
}
func asyncWrapper() async -> String {
return await withCheckedContinuation { continuation in
legacyAPI { result in
continuation.resume(returning: result)
}
}
}
Task {
let result = await asyncWrapper()
print(result) // 输出:传统 API 数据
}
Continuation
让传统的回调风格代码可以轻松迁移到新的异步模型中。
🔒 9. Sendable
:并发环境下的数据安全
#
✅ 确保类型在多线程间安全传递:
#
struct User: Sendable {
let name: String
let age: Int
}
let user = User(name: "Alice", age: 30)
Task.detached {
print(user.name) // `User` 是线程安全的
}
@Sendable
确保数据在跨线程传递时没有副作用,避免竞争条件。
🚦 10. Structured Concurrency(结构化并发)
#
- 核心理念: 父任务创建的子任务会与其共享生命周期,父任务结束时,子任务也会自动取消。
- 优点:
- 自动管理内存和资源,减少内存泄漏的风险。
- 清晰的错误传播链路,方便调试。
✅ 示例:
#
func parentTask() async {
await withTaskGroup(of: Void.self) { group in
group.addTask { print("子任务 1 执行中") }
group.addTask { print("子任务 2 执行中") }
}
print("父任务完成")
}
Task {
await parentTask()
}
🚀 总结:Swift 并发的全景图
#
模块 | 作用 | 适用场景 |
---|
async/await | 简化异步编程,顺序化异步代码 | 网络请求、数据库操作等异步任务 |
Task | 轻量级任务管理,支持取消和优先级 | 并发执行后台任务 |
TaskGroup | 并发任务组管理,适合批量任务 | 并发加载数据、批量计算 |
Actor | 线程安全的数据保护机制 | 数据共享、避免数据竞争 |
@MainActor | 保证主线程执行,适合 UI 相关任务 | SwiftUI、UIKit 更新 |
AsyncSequence | 异步数据流处理,适合流式数据 | WebSocket、实时数据流 |
Continuation | 兼容旧回调风格代码,平滑过渡到新并发模型 | 第三方库、遗留 API 封装 |
Sendable | 并发环境下的数据安全标记 | 线程间数据共享 |
Structured Concurrency | 父子任务结构化管理,自动处理生命周期 | 高并发任务调度、复杂异步流程控制 |