核心概念
@concurrent
是 Swift 6.2 引入的新特性,用于明确标记需要卸载到全局执行器(后台线程)的函数。它与 nonisolated(nonsending)
共同构成 Swift 并发模型的改进,旨在解决以下问题:
- 行为统一
消除异步/同步函数在隔离行为上的不一致性 - 显式意图
明确标识需要并发执行的代码 - 简化复杂度
减少不必要的并发隔离域
关键机制解析
1. nonisolated(nonsending)
(统一行为)
swift
// 始终在调用者的执行器上运行
nonisolated(nonsending) func decode<T: Decodable>(_ data: Data) async throws -> T
版本 | 行为差异 |
---|---|
Swift 6.1 | 异步函数 → 全局执行器 |
Swift 6.1 | 同步函数 → 调用者执行器 |
Swift 6.2 | 统一在调用者执行器运行 |
2. @concurrent
(显式卸载)
swift
// 明确卸载到全局执行器
@concurrent func decode<T: Decodable>(_ data: Data) async throws -> T
特性 | 说明 |
---|---|
自动标记 nonisolated |
无需额外声明 |
创建新隔离域 | 要求状态实现 Sendable |
使用限制 | 不能与显式隔离声明(如 @MainActor )共存 |
何时使用 @concurrent
适用场景
swift
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 |
使用场景 | 兼容旧版 | 默认推荐 | 显式并发需求 |
代码可读性 | 意图模糊 | 行为明确 | 意图明确 |