swift (五) 并发

21 阅读2分钟

async await

// 模拟耗时操作(休眠)
func doWork() async -> String {
    // 休眠1秒,单位:纳秒
    try? await Task.sleep(nanoseconds: 1_000_000_000)
    return "任务执行完成"
}

// 调用:必须包裹在 Task 中
Task {
    let result = await doWork()
    print(result)
}
enum NetError: Error {
    case invalidUrl, networkFail
}

func fetchData() async throws -> String {
    try await Task.sleep(nanoseconds: 800_000_000)
    throw NetError.networkFail
}

// 调用
Task {
    do {
        let data = try await fetchData()
        print(data)
    } catch {
        print("请求失败:\(error)")
    }
}

Task 基础(创建、取消、优先级)

// 模拟耗时操作(休眠)
func doWork() async -> String {
    // 休眠1秒,单位:纳秒
    try? await Task.sleep(nanoseconds: 1_000_000_000)
    return "任务执行完成"
}

// 1. 普通 Task(继承上下文)
let normalTask = Task(priority: .medium) {
    await doWork()
}

// 2. 等待任务返回结果
Task {
    let res = await normalTask.value
    print(res)
}

// 3. 取消任务
normalTask.cancel()

// 4. 独立脱离任务(不继承 Actor/优先级)
Task.detached(priority: .background) {
    print("后台独立任务")
}

// 5. 任务内判断是否被取消
func checkCancelTask() async {
    if Task.isCancelled {
        print("任务已取消,终止执行")
        return
    }
    // 正常逻辑
}

并行多任务

async let(固定数量任务,推荐)

func taskA() async -> String { "接口A数据" }
func taskB() async -> String { "接口B数据" }

Task {
    // 并行启动
    async let a = taskA()
    async let b = taskB()
    // 统一等待
    let (resA, resB) = await (a, b)
    print(resA, resB)
}

TaskGroup(动态数量任务)

// 批量并发请求,可抛错
func batchRequest() async throws -> [String] {
    try await withThrowingTaskGroup(of: String.self) { group in
        let list = ["url1", "url2", "url3"]

        for item in list {
            group.addTask {
                try await fetchData() + " -> \(item)"
            }
        }

        var results = [String]()
        for try await res in group {
            results.append(res)
        }
        return results
    }
}

// 调用
Task {
    do {
        let datas = try await batchRequest()
        print(datas)
    } catch {
        print("批量请求失败")
    }
}

Actor 线程安全(替代锁)

actor SafeCounter {
    private var count = 0

    func increase() {
        count += 1
    }

    func getCount() -> Int {
        count
    }

    // 无状态方法,免 await 调用
    nonisolated func tip() -> String {
        "计数器"
    }
}

// 使用
Task {
    let counter = SafeCounter()
    await counter.increase()
    print(await counter.getCount()) // 1
    print(counter.tip()) // 无需 await
}
// 整个类绑定主线程
@MainActor
class UIViewModel {
    var content: String = ""

    func updateText(_ text: String) {
        content = text
    }
}

// 后台加载数据 + 主线程刷新UI
func loadAndRefreshUI(vm: UIViewModel) async {
    let netData = await doWork()
    // 切回主线程更新UI
    await MainActor.run {
        vm.updateText(netData)
        print(vm.content)
    }
}

// 调用
Task {
    let vm = UIViewModel()
    await loadAndRefreshUI(vm: vm)
}

Sendable 类型安全标记

// 1. 值类型默认 Sendable(显式声明更规范)
struct User: Sendable {
    let id: Int
    let name: String
}

// 2. 加锁类(手动标记 @unchecked Sendable)
class LockedModel: @unchecked Sendable {
    private let lock = NSLock()
    private var num = 0

    var value: Int {
        get {
            lock.lock()
            defer { lock.unlock() }
            return num
        }
        set {
            lock.lock()
            defer { lock.unlock() }
            num = newValue
        }
    }
}