核心概念
@concurrent
是 Swift 6.2 引入的新特性,用于明确标记需要卸载到全局执行器(后台线程)的函数。它与 nonisolated(nonsending)
共同构成 Swift 并发模型的改进,旨在解决以下问题:
-
行为统一
消除异步/同步函数在隔离行为上的不一致性
-
显式意图
明确标识需要并发执行的代码
-
简化复杂度
减少不必要的并发隔离域
关键机制解析
1. nonisolated(nonsending)
(统一行为)
// 始终在调用者的执行器上运行
nonisolated(nonsending) func decode<T: Decodable>(_ data: Data) async throws -> T
版本 |
行为差异 |
Swift 6.1 |
异步函数 → 全局执行器 |
Swift 6.1 |
同步函数 → 调用者执行器 |
Swift 6.2 |
统一在调用者执行器运行 |
2. @concurrent
(显式卸载)
// 明确卸载到全局执行器
@concurrent func decode<T: Decodable>(_ data: Data) async throws -> T
特性 |
说明 |
自动标记 nonisolated
|
无需额外声明 |
创建新隔离域 |
要求状态实现 Sendable
|
使用限制 |
不能与显式隔离声明(如 @MainActor )共存 |
何时使用 @concurrent
适用场景
class Networking {
// 主线程安全的网络请求
func loadData(from url: URL) async throws -> Data { ... }
// 耗时解码 → 适合 @concurrent
@concurrent func decode<T: Decodable>(_ data: Data) async throws -> T {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
}
func getFeed() async throws -> Feed {
let data = try await loadData(from: Feed.endpoint)
// 避免阻塞调用者线程
let feed: Feed = try await decode(data)
return feed
}
}
使用原则
-
精准定位
仅标记实际需要并发的函数(如 CPU 密集型任务)
-
避免过度使用
减少不必要的隔离域和 Sendable
约束
-
性能优化
解决特定性能瓶颈(如大数据量解码)
总结对比表
特性 |
nonisolated (旧) |
nonisolated(nonsending) |
@concurrent |
执行位置 |
异步→全局/同步→调用者 |
始终在调用者执行器 |
全局执行器 |
隔离域 |
可能创建新隔离域 |
不创建新隔离域 |
创建新隔离域 |
状态要求 |
潜在需要 Sendable
|
无特殊要求 |
必须 Sendable
|
使用场景 |
兼容旧版 |
默认推荐 |
显式并发需求 |
代码可读性 |
意图模糊 |
行为明确 |
意图明确 |