Swift Concurrency并发是Apple在 Swift 5.5(随 iOS 15 / macOS 12 引入)中推出的一套现代并发编程模型,核心是以结构化并发为基础的 async/await 语法、Task 和 Actor 等组件。相比传统的 GCD,它更安全、更可读、更易于维护。
Swift并发编程的发展演进
Swift Concurrency 引入之前(Swift < 5.5)
时间点:Swift 初期(iOS 4 时代开始,一直沿用至今)
特点:
1、使用 DispatchQueue.async 实现异步操作。
2、底层基于 C 的 API,灵活但易出错。
3、手动线程切换,嵌套回调严重。
代码示例:
DispatchQueue.global().async {
// 假设这个是耗时操作,如网络请求
let data = fetchData()
DispatchQueue.main.async {
self.label.text = data.title
}
}
问题:
1、容易嵌套多层 callback(回调地狱)。
2、容易忘记切回主线程导致 UI 崩溃。
3、错误传播复杂。
4、很难读出任务执行顺序。
Swift Concurrency 引入之后(Swift 5.5+)
时间点:Swift 5.5(iOS 13+/macOS 10.15+)起,正式稳定
核心特性:
1、async/await 简化异步操作。
2、Task 任务系统,结构化并发。
3、actor 实现数据并发隔离(取代传统锁)。
4、自动线程跳转(如主线程更新 UI)。
代码示例:
func loadData() async {
let (data, _) = try await URLSession.shared.data(from: url)
let model = try JSONDecoder().decode(MyModel.self, from: data)
self.label.text = model.name
}
优势:
1、写法直观,无需嵌套。
2、错误处理统一 try/await。
3、自动线程管理,更安全。
4、容易维护、测试。
核心概念
1、async / await
用于声明异步函数并等待其完成,避免“回调地狱”。
func fetchUserData() async throws -> User {
// 异步网络请求
}
Task {
do {
let user = try await fetchUserData()
print(user)
} catch {
print("Error:", error)
}
}
通过使用 async 和 await,可以编写非阻塞的代码,处理需要等待完成的任务,比如网络请求、文件读写等。避免使用复杂的回调或闭包,代码变得更加直观和易于理解,相关文章《Swift UI 深入理解async和await》。
2、Task
用于启动一个新的并发任务。
Task {
await doSomething()
}
可以设置优先级:
Task(priority: .high) {
await fetchData()
}
也可以取消:
let task = Task {
try await longRunningTask()
}
task.cancel()
Task 是一种用于启动、管理和控制异步操作的轻量级结构。它不是线程,而是运行在 Swift 并发运行时中的“协程任务”。相关知识请见《Swift并发模型中的Task》。
3、TaskGroup 和 async let
用于并发执行多个异步任务并聚合结果。
async let(结构化并发):
async let image1 = loadImage(from: url1)
async let image2 = loadImage(from: url2)
let (img1, img2) = await (image1, image2)
TaskGroup(动态并发任务):
func fetchAll() async throws -> [Data] {
try await withThrowingTaskGroup(of: Data.self) { group in
for url in urls {
group.addTask {
try await fetch(url)
}
}
var results: [Data] = []
for try await data in group {
results.append(data)
}
return results
}
}
TaskGroup 和 async let 都是用于并发并行执行多个异步任务的工具,但它们各自适用于不同的场景。
async let:并发启动多个已知数量的异步任务,适合数量固定、结构清晰的并发。
TaskGroup:动态创建多个异步任务并等待全部完成,适合数量不定、动态生成的任务。
更多知识详见《Swift并发模型中的TaskGroup和async let》。
4、Actor
用于保护共享状态,避免数据竞争(数据一致性保证)。
actor Counter {
private var value = 0
func increment() {
value += 1
}
func getValue() -> Int {
value
}
}
let counter = Counter()
await counter.increment()
let val = await counter.getValue()
Actors和Class都是引用类型,与Class类似,但是Actor主要用于保护共享状态的并发常见。
因此,只有在需要多线程访问同一个对象时,才使用Actor。
更多知识详见《Swift并发模型中的Actor》。
主线程执行 (MainActor)
@MainActor
class ViewModel: ObservableObject {
@Published var text = ""
func updateText() {
text = "Updated"
}
}
或用于函数:
@MainActor
func updateUI() {
label.text = "Done"
}
这里的text赋值都涉及到UI操作,因此需要在方法或者类的顶部声明@MainActor,将代码操作切换回主线程。相关文章请见《Swift主线程标记@MainActor》
异步上下文
在 async 函数或 Task 中执行代码时,就处于“异步上下文”中。
具体来说,以下情况是“异步上下文”:
1、async 函数体内:
func fetchData() async {
// 这里是异步上下文
}
2、Task 或 Task.detached 中的闭包:
Task {
// 这里是异步上下文
}
3、await 后续的代码:
func someAsyncFunction() async {
await doSomething()
// 这里仍是异步上下文
}
Swift 6 开启了“严格的并发检查”,在异步上下文中不能随意访问主线程相关的内容(例如 Thread.isMainThread)。
DispatchQueue.global().async {
print("现在在哪?", Thread.isMainThread) // false
Task {
print("Task 在哪?", Thread.isMainThread) // 报错提示行
}
}
会输出:
Class property 'isMainThread' is unavailable from asynchronous contexts; Work intended for the main actor should be marked with @MainActor; this is an error in the Swift 6 language mode
异步上下文可能不在主线程上,访问主线程资源是不安全的,编译器会报错。
因此,应该使用 @MainActor 或 MainActor.run:
Task {
await MainActor.run {
print("这里安全地在主线程中运行")
}
}
Concurrency本质
Swift Concurrency 是一整套并发运行时 + 类型安全机制
1、Swift 运行时中引入了协作式任务调度(Cooperative Task Scheduling)
并不是用传统线程池(如 GCD),而是使用更轻量的任务(Task)调度器。
调度器运行在少量线程上,会在挂起点 await 自动让出资源,提升并发效率。
优势是节省线程开销,性能更高,避免线程爆炸。
2、引入结构化并发(Structured Concurrency)
每个 Task 是有父子层级关系的,自动管理生命周期。
自动传播 cancel、error,避免资源泄漏。
这是现代语言并发设计的核心,比如 Kotlin Coroutine、Rust Future 都有类似概念。
3、类型系统中新增 Sendable / @Sendable
编译器会检查在并发中共享的数据是否安全。
防止并发线程中访问非线程安全对象。
Actor 内部隔离状态,同时让类型系统保证并发安全。
4、Actor 实际上封装了一个串行任务队列
Actor 就像“线程安全类”,发消息(调用方法)给它,它自动按顺序执行。
替代了锁(mutex、semaphore),并发逻辑更简洁安全。
Swift 编译器确保只能通过异步方法访问 Actor 的内部状态。
5、引入隔离域(Isolation Domain)
比如 @MainActor 是一个特殊的隔离域,代码在主线程上串行运行。
编译器会自动插入线程切换逻辑,防止错误线程访问 UI。
所有 Actor 都运行在各自的隔离域中,隔离的数据访问。
总结
Swift Concurrency 是语言级的并发模型,结合语法、调度器、类型系统和运行时,构建了安全、高效、可读的异步并发执行体系。
扩展知识
async/await和“回调地狱”
在正文中说到async/await 避免了“回调地狱”,是因为它彻底改变了异步代码的写法,让“同步的方式编写异步逻辑”,不再陷入一层层嵌套的回调结构。
什么是“回调地狱”?
“回调地狱”通常长这样:
loadUser { user in
fetchPosts(for: user) { posts in
downloadImages(for: posts) { images in
updateUI(with: images)
}
}
}
1、每一层都是一个闭包(callback)。
2、缩进越来越深,可读性变差。
3、错误处理复杂(每层都要处理)。
4、难以写“顺序逻辑”,比如:加载 → 解析 → 展示。
回调地狱本质上是“异步调用的嵌套”结构。常见于:
1、网络请求完成后通知。
2、文件下载完成后通知。
3、延迟执行后的处理。
4、等待某个事件触发再执行处理逻辑。
async/await 的写法
使用 async/await,你可以把上面的代码重写为:
func loadAll() async {
let user = await loadUser()
let posts = await fetchPosts(for: user)
let images = await downloadImages(for: posts)
updateUI(with: images)
}
看起来像是“同步写法”,但执行依然是异步的:
1、代码结构扁平、清晰
2、按照自然的顺序思考逻辑
3、错误处理也统一、简洁(可用 do-catch)
await 会在编译时被转成状态机,每个 await 之后的代码被保存在 continuation 中(下一步执行),这样可以暂停当前函数,等结果回来后自动恢复继续运行。
async/await 只能用来调用异步函数。
相关文章
1、Swift管理多线程任务框架GCD:https://fangjunyu.com/2024/11/02/swift%e7%ae%a1%e7%90%86%e5%a4%9a%e7%ba%bf%e7%a8%8b%e4%bb%bb%e5%8a%a1%e6%a1%86%e6%9e%b6gcd/
2、Swift UI 深入理解async和await:https://fangjunyu.com/2024/10/12/swift-ui-%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3async%e5%92%8cawait/
3、Swift主进程:https://fangjunyu.com/2024/12/25/swift%e4%b8%bb%e7%ba%bf%e7%a8%8b/
4、Swift并发模型中的Task.result属性:https://fangjunyu.com/2024/12/09/swift%e5%b9%b6%e5%8f%91%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84task-result%e5%b1%9e%e6%80%a7/
5、Swift并发模型中的Task:https://fangjunyu.com/2025/05/15/swift%e5%b9%b6%e5%8f%91%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84task/
6、Swift主线程标记@MainActor:https://fangjunyu.com/2024/12/25/swift%e4%b8%bb%e7%ba%bf%e7%a8%8b%e6%a0%87%e8%ae%b0mainactor/
7、Swift并发模型中的MainActor.run方法:https://fangjunyu.com/2025/05/15/swift%e5%b9%b6%e5%8f%91%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84mainactor-run%e6%96%b9%e6%b3%95/
8、Swift并发模型中的TaskGroup和async let:https://fangjunyu.com/2025/05/15/swift%e5%b9%b6%e5%8f%91%e6%a8%a1%e5%9e%8b%e4%b8%ad%e7%9a%84taskgroup%e5%92%8casync-let/
9、Swift并发模型中的Actor:https://fangjunyu.com/2024/10/22/swift%e7%a7%91%e6%99%ae%e6%96%87%e3%80%8aactor-%e9%9a%94%e7%a6%bb%e3%80%8b/