Swift Actor 是 Swift 并发编程模型的一部分,从 Swift 5.5 开始引入。Actor 用于管理共享状态,通过隔离确保对状态的互斥访问,从而避免数据竞争。以下是关于 Swift Actor 的详细说明:
-
Actor 的定义:
- Actor 是一种引用类型,类似于类,但不同之处在于 Actor 一次只允许一个任务访问其可变状态。
- 定义 Actor 使用
actor关键字。
-
Actor 的特性:
- Actor 内部的状态(属性和方法)默认是隔离的,外部代码不能直接访问,除非通过
await调用。 - Actor 内部可以定义方法和属性,其中方法分为两种:可异步访问的和不可异步访问的(但外部访问都必须通过
await)。 - Actor 内部可以定义同步方法,但外部调用时仍然需要
await,因为调用可能会被挂起直到 Actor 空闲。
- Actor 内部的状态(属性和方法)默认是隔离的,外部代码不能直接访问,除非通过
-
Actor 的使用场景:
- 当多个任务需要访问和修改共享数据时,使用 Actor 可以保证数据安全。
- 例如,多个任务同时操作一个计数器,使用 Actor 可以确保每次修改都是原子的。
-
Actor 的示例:
actor Counter {
private var value = 0
func increment() -> Int {
value += 1
return value
}
func getValue() -> Int {
return value
}
}
// 使用 Actor
let counter = Counter()
Task {
let value = await counter.increment()
print(value) // 输出 1
}
Task {
let value = await counter.increment()
print(value) // 输出 2
}
-
Actor 的注意事项:
- 不能直接从一个 Actor 内部方法中调用另一个 Actor 的方法,因为可能会造成死锁。如果需要,可以使用
async方法并await调用。 - Actor 内部可以使用
nonisolated关键字标记不需要隔离的成员,这样外部访问时就不需要await。
- 不能直接从一个 Actor 内部方法中调用另一个 Actor 的方法,因为可能会造成死锁。如果需要,可以使用
-
Actor 与数据竞争:
- Actor 通过隔离状态来防止数据竞争,但并不能防止所有的并发问题,比如死锁。因此,在设计 Actor 时需要注意避免长时间占用 Actor 而导致其他任务等待。
-
Actor 与
@MainActor:@MainActor是一个特殊的 Actor,它运行在主线程上,用于更新 UI。任何标记为@MainActor的代码都必须运行在主线程上。
-
Actor 的性能:
- Actor 通过串行队列来管理任务,所以如果 Actor 中的任务执行时间很长,会阻塞其他等待该 Actor 的任务。因此,在 Actor 中应避免执行耗时操作。
-
Actor 的继承:
- Actor 不能继承自其他类或 Actor,但可以遵守协议。
-
Actor 和
Sendable:- Actor 内部的状态必须是
Sendable的,即可以安全地在并发环境中传递。这包括值类型、不可变类或本身是 Actor 的类型。
- Actor 内部的状态必须是
Swift Actor 是 Swift 并发模型的核心组成部分,用于安全地管理共享状态,防止数据竞争。