1、Swift并发编程概述:为什么需要并发?
说实话,我刚开始做iOS开发那会儿,并发还是个挺「高级」的话题。那时候大家用的还是Objective-C,处理异步任务全靠Delegate和Block来回传。一个网络请求下来,回调里套回调,代码写得跟俄罗斯套娃似的。
后来Swift出来了,带来了GCD(Grand Central Dispatch)。嗯,这确实是个好东西。但说实话,用起来还是有点别扭——你得手动管理队列、处理线程安全、小心死锁。我有个项目就因为dispatch_sync用错了地方,直接卡死了主线程,用户反馈说「点按钮没反应」,排查了半天才发现问题。
现在好了,Swift 5.5引入了async/await和Actor。这不仅仅是语法糖,而是从根本上改变了我们写并发代码的方式。你想想看,以前写异步代码就像在走迷宫,现在有了async/await,就像有了张地图。
为什么我们需要并发?
这个问题我问过不少刚入行的朋友。他们的回答往往是:「为了让App跑得更快呗。」
对,但不全对。
并发真正的价值在于:让多个任务「看起来」在同时执行。比如用户刷朋友圈时,图片在后台加载、视频在预缓存、新消息在推送——这些事如果串着做,用户体验会非常糟糕。
我举个例子。你打开一个新闻App,首页需要做三件事:
- 拉取新闻列表数据
- 下载封面图片
- 检查是否有新版本更新
如果串行执行,总耗时可能是 300ms + 500ms + 200ms = 1000ms。用户得等整整一秒才能看到内容。但如果并发执行,最慢的那个任务决定了总耗时——500ms。体验直接翻倍。
核心观点:并发不是为了「更快」,而是为了「更高效地利用等待时间」。网络请求在等服务器响应时,CPU完全可以去做别的事。
Swift并发模型演进:从GCD到async/await
咱们来捋一捋Swift并发的发展史。我把它分成三个阶段:
| 阶段 | 技术 | 特点 | 痛点 |
|---|---|---|---|
| 第一阶段 | Delegate + Block | 手动管理回调 | 回调地狱、难以调试 |
| 第二阶段 | GCD + OperationQueue | 队列管理、任务调度 | 线程安全、死锁风险 |
| 第三阶段 | async/await + Actor | 结构化并发、自动安全 | 学习曲线、兼容性 |
GCD时代,我们写代码大概是这样的:
DispatchQueue.global().async {
let data = fetchData() // 网络请求
DispatchQueue.main.async {
self.label.text = data.title
}
}
看着还行对吧?但实际项目中,嵌套个三四层是常有的事。我曾经维护过一个老项目,一个登录流程嵌套了七层回调,每次改需求都得花半天理清逻辑。
async/await时代,同样的逻辑变成了:
func loadData() async {
let data = await fetchData()
label.text = data.title
}
简洁、直观、线性。你不需要手动切换队列,系统会自动处理好上下文。说白了,就是把「怎么调度」这件事交给了编译器,你只需要关心「做什么」。
我的建议:如果你还在用GCD写新项目,可以考虑逐步迁移了。async/await不是银弹,但它确实让代码更容易理解和维护。尤其是团队协作时,新人上手快很多。
Actor:解决数据竞争的利器
说到并发,就绕不开数据竞争。多个线程同时读写同一个变量,结果不可预测。GCD时代我们靠锁来解决——NSLock、@synchronized、串行队列……但锁用多了,死锁、性能下降都是家常便饭。
Actor的出现,算是从根源上解决了这个问题。它保证:同一时刻,只有一个任务能访问Actor内部的状态。
actor Counter {
private var value = 0
func increment() {
value += 1
}
func getValue() -> Int {
return value
}
}
let counter = Counter()
await counter.increment()
let current = await counter.getValue()
你看,不需要加锁,不需要手动同步。编译器帮你做了所有安全校验。我在一个即时通讯项目里用Actor管理消息队列,以前用GCD时偶尔会出现消息顺序错乱的问题,换成Actor后一次都没出过。
注意:Actor不是万能的。它解决的是「数据竞争」问题,但「死锁」和「优先级反转」仍然可能发生。尤其是当你用Actor嵌套调用时,要小心潜在的循环等待。
课程目标与学习路径
这门课的目标很明确:让你真正掌握Swift并发编程,能写出安全、高效、可维护的并发代码。
我把它分成四个阶段:
- 基础篇(第1-8章):理解async/await语法、Task、结构化并发。学完能写出基本的异步函数。
- 进阶篇(第9-16章):深入Actor、Sendable协议、全局Actor。学会处理复杂的数据共享场景。
- 实战篇(第17-24章):结合UIKit/SwiftUI、网络层、数据库操作。用真实项目案例巩固知识。
- 高阶篇(第25-30章):性能优化、调试技巧、与Combine/Objective-C混编。成为团队里的并发专家。
每个章节我都会结合自己踩过的坑来讲。比如第5章讲Task取消时,我会分享一个因为忘记处理取消导致内存泄漏的真实案例。第12章讲Actor重入时,我会演示一个看似正确实则危险的代码模式。
学习建议:别光看,一定要动手写。每章后面的练习至少做一遍。并发编程这东西,看十遍不如写一遍。我见过太多人「看懂了」但「写不出来」——因为并发的问题往往在运行时才暴露。
好了,第一章就到这里。下一章我们正式进入async/await的世界,从最基础的语法开始。准备好了吗?