并发编程 — Actor

在 Swift 中,actor 是一种并发编程模型,用于保护共享状态,防止数据竞争(Data Race)。它在 Swift 5.5 引入,属于 Swift 并发体系的一部分。

1. Actor 的核心概念 #

actor 类似于 class,但它的内部状态是线程安全的。Actor 可以封装数据,确保这些数据只能被一个任务同时访问,从而避免多线程环境下常见的竞争条件。

actor Counter {
    private var value = 0

    func increment() {
        value += 1
    }

    func getValue() -> Int {
        return value
    }
}

2. Actor 的使用方式 #

  • 实例化 Actor:
let counter = Counter()
  • 异步调用方法:
    Actor 的方法默认是异步的,因为它们可能会被多个任务竞争访问。
Task {
    await counter.increment()
    let currentValue = await counter.getValue()
    print(currentValue)
}
  • 内部同步访问:
    Actor 内部的方法或属性可以直接访问内部状态,无需使用 await,因为此时不存在并发冲突。
actor BankAccount {
    private var balance = 0

    func deposit(_ amount: Int) {
        balance += amount
    }

    func getBalance() -> Int {
        balance  // 直接访问,无需 await
    }
}

3. 为什么使用 Actor #

  • 线程安全: 不需要手动加锁,Actor 自己管理并发访问。
  • 简化代码: 避免复杂的 DispatchQueuelock 等并发工具。
  • 与异步/等待(async/await)结合紧密: 更自然地处理异步代码。

4. Actor 的限制 #

  • 不能同步访问: 不能像普通类那样直接访问 Actor 的属性或方法,必须使用 await
  • 性能开销: Actor 引入了一定的调度开销,尤其在频繁调用的场景下。

5. Non-Isolated 与 @MainActor #

  • nonisolated 标记方法为非隔离,允许在 Actor 外部同步调用,适用于不依赖内部状态的方法。
actor Logger {
    nonisolated func log(_ message: String) {
        print(message)  // 不访问内部状态,线程安全
    }
}
  • @MainActor 指定代码必须在主线程运行,常用于更新 UI。
@MainActor
class ViewModel {
    func updateUI() {
        // 主线程安全执行
    }
}

总结 #

  • actor 是 Swift 并发模型中的线程安全容器,自动管理数据访问冲突。
  • async/await 紧密集成,适合现代异步编程需求。
  • 适用于需要保证数据一致性的并发场景,比如网络请求、数据处理等。
本文共 698 字,创建于 Feb 5, 2025
相关标签: Swift, Xcode