在 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 自己管理并发访问。
- 简化代码: 避免复杂的
DispatchQueue
、lock
等并发工具。 - 与异步/等待(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
紧密集成,适合现代异步编程需求。 - 适用于需要保证数据一致性的并发场景,比如网络请求、数据处理等。