Swift 中的并发与多线程:高级水平

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 中的并发与多线程:高级水平

\n\n

现代 iOS 和 macOS 应用程序需要高性能和响应式界面。Swift 中的高级并发处理远不止简单使用 Grand Central Dispatch (GCD)。在本文中,我们将探讨 Swift 5.5+ 中用于管理异步任务的关键工具:async/await、Actors、TaskGroup 和 Sendable 协议。您将学习如何避免数据竞争、正确构建多线程代码以及优化性能。

\n\n

1. async/await 与结构化并发基础

\n\n

关键字 async 和 await 是现代 Swift 并发的基础。它们允许编写看起来像同步代码的异步代码,从而大大简化了阅读和调试。

\n\n

声明异步函数:

\n
func fetchUserData() async throws -> User {\n    let url = URL(string: "https://api.example.com/user")!\n    let (data, _) = try await URLSession.shared.data(from: url)\n    let decoder = JSONDecoder()\n    return try decoder.decode(User.self, from: data)\n}
\n\n

调用异步函数并处理错误:

\n
Task {\n    do {\n        let user = try await fetchUserData()\n        print("User name: \\(user.name)")\n    } catch {\n        print("Failed to fetch user: \\(error)")\n    }\n}
\n\n

重要事项:

\n
    \n
  • 结构化并发: 每个异步任务都有明确的生存期,受父级 Task 作用域的限制。
  • \n
  • 任务取消: 当父级 Task 被取消时,子任务会自动取消。
  • \n
  • 优先级: 对于用户重要的任务,使用 Task(priority: .userInitiated)。
  • \n
\n\n

2. Actors:防止数据竞争

\n\n

在 Swift 5.5 之前,开发者经常使用 GCD 的串行队列来保护共享状态。Actors 提供了内置的隔离机制:只能通过 await 访问 actor 的状态,这保证了编译器级别的线程安全。

\n\n

银行账户的 Actor 示例:

\n
actor BankAccount {\n    private var balance: Double = 0.0\n\n    func deposit(amount: Double) {\n        balance += amount\n    }\n\n    func withdraw(amount: Double) throws {\n        guard balance >= amount else {\n            throw BankError.insufficientFunds\n        }\n        balance -= amount\n    }\n\n    func getBalance() -> Double {\n        return balance\n    }\n}\n\n// 使用\nlet account = BankAccount()\nTask {\n    await account.deposit(amount: 100.0)\n    let currentBalance = await account.getBalance()\n    print("Balance: \\(currentBalance)")\n}
\n\n

Actors 的优势:

\n
    \n
  • 编译器检查: 尝试在没有 await 的情况下访问 actor 的属性会导致编译错误。
  • \n
  • 重入性: Actor 可以暂停当前方法的执行(例如,在 actor 内部使用 await 时)并处理另一个调用,从而防止死锁。
  • \n
  • 性能: Actors 使用优化的同步机制,通常比手动锁更快。
  • \n
\n\n

3. TaskGroup:并行数据处理

\n\n

当需要执行多个独立的异步操作并等待它们全部完成时,TaskGroup 是理想的工具。它会自动管理并行任务的数量并收集结果。

\n\n

并行下载多个图像的示例:

\n
func downloadImages(urls: [URL])                

博客

书籍推荐