我正在学习
async-await
的用法,并同时阅读有关 Global Actors
的内容。我知道MainActor
是GlobalActor
,如果我们用@mainActor
注释一个方法,该方法将在主线程上执行。类似于如果我们创建一个自定义的 GlobalActor,我们是否知道它将使用哪个线程来执行。
@globalActor actor CustomGlobalActor {
static let shared = CustomGlobalActor()
}
@CustomGlobalActor func performTask() async -> Output {
.....
}
另外,还有其他问题:
一些观察:
“全局参与者”(如SE-0316中定义)只是一个可全局访问的命名的参与者。如果您定义自己的全局参与者,则可以在整个应用程序中通过该名称全局访问该特定参与者。
我知道你知道这一点,但主角也是一位全球演员。它只是一种特殊的、预定义的、恰好依赖于主线程的线程。 (类似于GCD的“主队列”只是一个恰好使用主线程的特殊调度队列。)
但是,请注意,当人们开始担心特定参与者上的特定任务正在使用什么线程时,该参与者是否是全局参与者并不重要。此时我们只关心演员的行为。出于本次对话的目的,我们并不特别关心演员是否是全球演员。只是因为它是一个演员。
此时可能不用说,“全局actor”的“全局”与GCD“全局”调度队列无关。它们是完全不同的概念。
你说:
类似于如果我们创建一个自定义的 GlobalActor,我们是否知道它将使用哪个线程来执行。
这有点吹毛求疵,但是,不,除了主要演员(与主线程相关)之外,一般演员并不与特定线程相关。 (无论如何,Swift 并发努力将我们从线程级细节中抽象出来。)
正如人们应该避免将线程和 GCD 调度队列混为一谈一样,actor 也是如此。如果您已将三个任务提交给某个非主要参与者,则您无法保证它们将在同一线程上运行。您只知道无论它们在什么线程上运行,该参与者上的不同任务都不会与同一参与者上的其他任务同时主动运行。由于特定参与者上的任务不会并行运行,因此它们很可能最终在同一线程上依次运行。但他们可能不会。
如果您对这些细节感兴趣,请参阅 WWDC 2021 Swift 并发:幕后。
是的,在实践中,在非主actor上运行的任务(无论它是否是全局actor)可以用于从主线程获取耗时的同步任务(例如某些计算密集型进程)。
但这不是演员的主要目的。它们更多的是允许我们管理不同任务之间的一些可变共享状态。请参阅 WWDC 2021 使用 Swift Actor 保护可变状态。
所以,如果你有一个计算密集型的计算,你想脱离主线程,是的,理论上你可以使用演员。如果您希望该演员成为全球演员,您也可以这样做(尽管这种情况不太常见)。但是,如果您想做的只是从主线程中获取一些计算密集型进程,您可能只使用
async
非隔离函数(请参阅 SE-0338)或分离任务,然后就到此为止了。 Actor 更多的是管理跨任务的状态,而不是从主线程中获取某些内容。