Swift 中的并发与多线程简介
现代移动和桌面应用程序必须快速且响应迅速。在 iOS 和 macOS 开发中,正确管理并发和多线程起着关键作用。Swift 提供了强大的工具来并行执行任务,从经典的 Grand Central Dispatch (GCD) 到现代的 async/await 模型和 Actor。
在本文中,我们将探讨 Swift 中处理线程的所有主要方法:从基本概念到高级技术。您将学习如何避免竞态条件、死锁以及其他多线程编程中常见的问题。
Grand Central Dispatch (GCD) — 多线程经典
Grand Central Dispatch (GCD) 是 Apple 用于管理代码并行执行的低级库。它使用队列(dispatch queues)将任务分配到线程。
队列的主要类型
GCD 中有两种主要类型的队列:
- 串行队列 (Serial queues): 任务按添加顺序一个接一个执行。非常适合同步对资源的访问。
- 并发队列 (Concurrent queues): 任务可以同时执行,完成顺序不保证。
GCD 使用示例
import Foundation
// 创建串行队列let serialQueue = DispatchQueue(label: "com.example.serial")
// 创建并发队列let concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
// 异步执行serialQueue.async { print("任务 1 在后台执行")}
// 同步执行(阻塞当前线程)serialQueue.sync { print("任务 2 同步执行")}
// 使用主线程DispatchQueue.main.async { print("在主线程更新 UI")}
// 延迟执行DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { print("2 秒后执行")}Dispatch Group — 任务组同步
Dispatch Group 允许跟踪一组异步任务的完成情况,并在它们全部完成后执行代码。
let group = DispatchGroup()let queue = DispatchQueue.global(qos: .background)
for i in 1...5 { queue.async(group: group) { print("任务 \\(i) 开始") Thread.sleep(forTimeInterval: Double.random(in: 0.5...2.0)) print("任务 \\(i) 完成") }}
group.notify(queue: DispatchQueue.main) { print("所有任务完成!更新 UI。")}Swift 5.5+ 中的现代 async/await
从 Swift 5.5 开始,Apple 引入了一种新的并发模型,基于关键字 async 和 await。这使得异步代码更易读、更清晰。
定义异步函数
异步函数使用关键字 async 标记,调用它们需要 await:
import Foundation
// 异步数据加载函数func fetchUserData() async throws -> String { let url = URL(string: "https://api.example.com/user")! let (data, _) = try await URLSession.shared.data(from: url) return String(data: data, encoding: .utf8) ?? "No data"}
// 使用 async/awaitfunc loadUserProfile() async { do { let userData = try await fetchUserData() await MainActor.run { print("用户数据: \\(userData)") } } catch { print("加载错误: \\(error)") }}
// 启动异步任务Task { await loadUserProfile()}Async let — 并行执行
关键字 async let 允许并行启动多个异步任务:
<