名称: swift-concurrency 描述: ‘关于Swift并发编程最佳实践、模式和实现的专家指导。当开发者提到以下内容时使用:(1) Swift并发、async/await、actors或tasks,(2) “使用Swift并发"或"现代并发模式”,(3) 迁移到Swift 6,(4) 数据竞争或线程安全问题,(5) 将闭包重构为async/await,(6) @MainActor、Sendable或actor隔离,(7) 并发代码架构或性能优化。’
Swift并发编程
概述
本技能提供关于Swift并发编程的专家指导,涵盖现代async/await模式、actors、tasks、Sendable一致性以及迁移到Swift 6。使用本技能帮助开发者编写安全、高性能的并发代码,并驾驭Swift结构化并发模型的复杂性。
代理行为契约(遵循这些规则)
- 分析项目/包文件,找出使用的Swift语言模式(Swift 5.x vs Swift 6)和Xcode/Swift工具链,当建议依赖于这些信息时。
- 在提出修复方案之前,识别隔离边界:
@MainActor、自定义actor、actor实例隔离或nonisolated。 - 不要将
@MainActor作为通用解决方案推荐。要证明为什么主actor隔离对该代码是正确的。 - 优先使用结构化并发(子任务、任务组)而非非结构化任务。仅在理由明确时使用
Task.detached。 - 如果推荐使用
@preconcurrency、@unchecked Sendable或nonisolated(unsafe),要求:- 有文档记录的安全不变量
- 创建后续工单以移除或迁移它
- 对于迁移工作,优化以最小化影响范围(小范围、可审查的更改)并添加验证步骤。
- 课程参考仅用于深入学习。仅在它们明显有助于回答开发者问题时才使用。
项目设置评估(在建议前评估)
并发行为取决于构建设置。始终尝试确定:
- 默认actor隔离(模块默认是
@MainActor还是nonisolated?) - 严格并发检查级别(minimal/targeted/complete)
- 是否启用了即将推出的功能(特别是
NonisolatedNonsendingByDefault) - Swift语言模式(Swift 5.x vs Swift 6)和SwiftPM工具版本
手动检查(无脚本)
- SwiftPM:
- 检查
Package.swift中的.defaultIsolation(MainActor.self)。 - 检查
Package.swift中的.enableUpcomingFeature("NonisolatedNonsendingByDefault")。 - 检查严格并发标志:
.enableExperimentalFeature("StrictConcurrency=targeted")(或类似)。 - 检查顶部的工具版本:
// swift-tools-version: ...
- 检查
- Xcode项目:
- 在
project.pbxproj中搜索:SWIFT_DEFAULT_ACTOR_ISOLATIONSWIFT_STRICT_CONCURRENCYSWIFT_UPCOMING_FEATURE_(和/或SWIFT_ENABLE_EXPERIMENTAL_FEATURES)
- 在
如果其中任何一项未知,请在给出与迁移相关的指导前请开发者确认。
快速决策树
当开发者需要并发指导时,遵循此决策树:
-
从头开始编写异步代码?
- 阅读
references/async-await-basics.md了解基础模式 - 对于并行操作 →
references/tasks.md(async let、任务组)
- 阅读
-
保护共享可变状态?
- 需要保护基于类的状态 →
references/actors.md(actors、@MainActor) - 需要线程安全的值传递 →
references/sendable.md(Sendable一致性)
- 需要保护基于类的状态 →
-
管理异步操作?
- 结构化异步工作 →
references/tasks.md(Task、子任务、取消) - 流式数据 →
references/async-sequences.md(AsyncSequence、AsyncStream)
- 结构化异步工作 →
-
与遗留框架协作?
- Core Data集成 →
references/core-data.md - 通用迁移 →
references/migration.md
- Core Data集成 →
-
性能或调试问题?
- 异步代码慢 →
references/performance.md(性能分析、挂起点) - 测试问题 →
references/testing.md(XCTest、Swift Testing)
- 异步代码慢 →
-
理解线程行为?
- 阅读
references/threading.md了解线程/任务关系和隔离
- 阅读
-
任务内存问题?
- 阅读
references/memory-management.md了解防止循环引用
- 阅读
分类优先手册(常见错误 -> 下一步最佳操作)
- “发送非Sendable类型的值…可能导致数据竞争”
- 首先:识别值在哪里跨越了隔离边界
- 然后:使用
references/sendable.md和references/threading.md(特别是Swift 6.2行为变化)
- “主actor隔离的…不能在非隔离上下文中使用”
- 首先:决定它是否真正属于
@MainActor - 然后:使用
references/actors.md(全局actors、nonisolated、隔离参数)和references/threading.md(默认隔离)
- 首先:决定它是否真正属于
- “类属性’current’在异步上下文中不可用”(Thread API)
- 使用
references/threading.md避免基于线程的调试,依赖隔离+Instruments
- 使用
- XCTest异步错误,如"wait(…)在异步上下文中不可用"
- 使用
references/testing.md(await fulfillment(of:)和Swift Testing模式)
- 使用
- Core Data并发警告/错误
- 使用
references/core-data.md(DAO/NSManagedObjectID、默认隔离冲突)
- 使用
核心模式参考
何时使用每种并发工具
async/await - 使现有同步代码异步化
// 适用于:单个异步操作
func fetchUser() async throws -> User {
try await networkClient.get("/user")
}
async let - 并行运行多个独立的异步操作
// 适用于:编译时已知的固定数量的并行操作
async let user = fetchUser()
async let posts = fetchPosts()
let profile = try await (user, posts)
Task - 启动非结构化异步工作
// 适用于:即发即弃操作,桥接同步到异步上下文
Task {
await updateUI()
}
Task Group - 具有结构化并发的动态并行操作
// 适用于:编译时未知数量的并行操作
await withTaskGroup(of: Result.self) { group in
for item in items {
group.addTask { await process(item) }
}
}
Actor - 保护可变状态免受数据竞争
// 适用于:从多个上下文访问的共享可变状态
actor DataCache {
private var cache: [String: Data] = [:]
func get(_ key: String) -> Data? { cache[key] }
}
@MainActor - 确保UI更新在主线程上
// 适用于:视图模型、UI相关类
@MainActor
class ViewModel: ObservableObject {
@Published var data: String = ""
}
常见场景
场景:带UI更新的网络请求
Task { @concurrent in
let data = try await fetchData() // 后台
await MainActor.run {
self.updateUI(with: data) // 主线程
}
}
场景:多个并行网络请求
async let users = fetchUsers()
async let posts = fetchPosts()
async let comments = fetchComments()
let (u, p, c) = try await (users, posts, comments)
场景:并行处理数组项
await withTaskGroup(of: ProcessedItem.self) { group in
for item in items {
group.addTask { await process(item) }
}
for await result in group {
results.append(result)
}
}
Swift 6迁移快速指南
Swift 6的关键变化:
- 严格并发检查默认启用
- 编译时完全数据竞争安全
- 在边界上强制执行Sendable要求
- 所有异步边界的隔离检查
详细迁移步骤,请参阅references/migration.md。
参考文件
根据需要加载这些文件以了解特定主题:
async-await-basics.md- async/await语法、执行顺序、async let、URLSession模式tasks.md- 任务生命周期、取消、优先级、任务组、结构化与非结构化threading.md- 线程/任务关系、挂起点、隔离域、nonisolatedmemory-management.md- 任务中的循环引用、内存安全模式actors.md- Actor隔离、@MainActor、全局actors、可重入性、自定义执行器、Mutexsendable.md- Sendable一致性、值/引用类型、@unchecked、区域隔离async-sequences.md- AsyncSequence、AsyncStream、何时使用vs常规异步方法core-data.md- NSManagedObject可发送性、自定义执行器、隔离冲突performance.md- 使用Instruments进行性能分析、减少挂起点、执行策略testing.md- XCTest异步模式、Swift Testing、并发测试工具migration.md- Swift 6迁移策略、闭包到异步转换、@preconcurrency、FRP迁移
最佳实践总结
- 优先使用结构化并发 - 尽可能使用任务组而非非结构化任务
- 最小化挂起点 - 保持actor隔离部分小以减少上下文切换
- 明智使用@MainActor - 仅用于真正与UI相关的代码
- 使类型Sendable - 通过符合Sendable实现安全并发访问
- 处理取消 - 在长时间运行的操作中检查Task.isCancelled
- 避免阻塞 - 绝不在异步上下文中使用信号量或锁
- 测试并发代码 - 使用适当的异步测试方法并考虑时序问题
验证清单(当您更改并发代码时)
- 在解释诊断信息之前确认构建设置(默认隔离、严格并发、即将推出的功能)。
- 重构后:
- 运行测试,特别是并发敏感测试(见
references/testing.md)。 - 如果与性能相关,使用Instruments验证(见
references/performance.md)。 - 如果与生命周期相关,验证deinit/取消行为(见
references/memory-management.md)。
- 运行测试,特别是并发敏感测试(见
术语表
有关本技能中使用的核心并发术语的快速定义,请参阅references/glossary.md。
注意:本技能基于Antoine van der Lee的全面Swift并发课程。