Swift 并发全景指南:Thread、Concurrency、Parallelism 一次搞懂

从底层线程到高层 Swift Concurrency,用代码带你吃透所有概念

为什么要关心这些概念?

  • 响应式 UI:主线程阻塞 = 卡死界面。
  • 高性能:多核 CPU 不并行 = 浪费算力。
  • 正确性:数据竞争 = 闪退或脏数据。

Thread:程序的最小执行单元

什么是 Thread

一条独立的执行路径,拥有独立的 栈 和 程序计数器,但与其他线程共享进程的内存空间。

手动创建 Thread(仅教学用,生产请用 GCD/Task)

swift 复制代码
import Foundation

func threadFunction() {
    for i in 1...3 {
        print("👾 Thread \(Thread.current) count \(i)")
        Thread.sleep(forTimeInterval: 0.3)
    }
}

let t = Thread {
    threadFunction()
}
t.start()          // 手动启动线程

⚠️ 直接使用 Thread 成本高、易出错;日常开发请使用 GCD 或 Swift Concurrency。

Concurrency vs. Parallelism:一对容易混淆的孪生兄弟

维度 Concurrency(并发) Parallelism(并行)
定义 交替推进多个任务 同时执行多个任务
CPU 核数 1 核即可 ≥2 核
目的 提高响应能力 提高吞吐量

并发示例(单核交替)

swift 复制代码
let queue = DispatchQueue(label: "concurrent", attributes: .concurrent)
queue.async { print("🍎 Task A") }
queue.async { print("🍏 Task B") }

单核 CPU 通过时间片轮转交替打印 A/B。

并行示例(多核同时)

swift 复制代码
DispatchQueue.concurrentPerform(iterations: 4) { i in
    print("🔥 Parallel \(i) on \(Thread.current)")
}

4 核机器会真正同时跑 4 条线程。

Swift 中的线程种类

线程 用途 注意
Main Thread UI 更新 & 用户交互 禁止长时间阻塞
Global Queue 默认后台线程池 QoS 分级(utility、background ...)

主线程 & 后台线程实战

swift 复制代码
// 1. 回到主线程刷新 UI
DispatchQueue.main.async {
    label.text = "Loaded"
}

// 2. 后台线程做重活
DispatchQueue.global(qos: .userInitiated).async {
    let img = self.resize(image: bigImage)
    DispatchQueue.main.async { imageView.image = img }
}

Thread Safety:别让数据"赛车"

问题示例:数据竞争

swift 复制代码
class UnsafeCounter {
    var value = 0
    func increment() { value += 1 }
}

在多线程环境下 value += 1 可能丢失更新(读-改-写非原子)。

解决方案速查表

技术 适用场景 示例
NSLock 低层临界区 见下方代码
串行 DispatchQueue 顺序执行任务 DispatchQueue(label: "serial")
Actor(Swift 5.5+) 高层、零锁代码 actor Counter { ... }

NSLock 示例

swift 复制代码
class SafeCounter {
    private var value = 0
    private let lock = NSLock()
    
    func increment() {
        lock.lock()
        defer { lock.unlock() }
        value += 1
    }
    
    func get() -> Int {
        lock.lock()
        defer { lock.unlock() }
        return value
    }
}

Actor 示例(推荐)

swift 复制代码
actor CounterActor {
    private var value = 0
    func increment() { value += 1 }
    func get() -> Int { value }
}

// 使用
let counter = CounterActor()
Task {
    await counter.increment()
    print(await counter.get())
}

真实世界场景演练

场景 并发模型 关键代码片段
Web 服务器 GCD + 并行队列 DispatchQueue.global().async { handle(request) }
图片滤镜 concurrentPerform DispatchQueue.concurrentPerform(iterations: count) { applyFilter($0) }
游戏引擎 多线程渲染 渲染线程 + 逻辑线程 + Actor 共享状态

思维导图:如何选择工具

arduino 复制代码
需求: 线程安全
├─ 只读数据 → 无需同步
├─ 低频写   → NSLock / 串行 queue
├─ 高频写   → Actor (零锁、可组合)
└─ 复杂依赖 → Task + Actor + AsyncSequence

常见问题 FAQ

问题 回答
何时用 Task vs DispatchQueue? 新项目优先 Task,老代码逐步迁移。
Actor 会降低性能吗? 轻微调度开销,远低于锁竞争。
MainActor 是什么? 系统预定义的全局 Actor,强制代码跑在主线程。

一句话总结

线程是地基,并发是设计思想,并行是多核福利;用 GCD/Task 管理线程,用 Actor/锁 保证安全,你的 Swift App 就能既快又稳。

相关推荐
HarderCoder4 小时前
Swift 数据容器全景手册:Sequence、Collection、Set、Dictionary 一次掌握
swift
HarderCoder5 小时前
深入理解 SOLID 原则:用 Swift 编写优雅、可维护的代码
swift
HarderCoder6 小时前
Swift 并发模型深度解析:Singleton 与 Global Actor 如何抉择?
swift
HarderCoder9 小时前
Swift Global Actor 完全指南
swift
HarderCoder9 小时前
Swift 计算属性(Computed Property)详解:原理、性能与实战
swift
HarderCoder9 小时前
Swift Property Wrapper:优雅地消除样板代码
swift
东坡肘子11 小时前
未来将至:人形机器人运动会 | 肘子的 Swift 周报 #099
swiftui·swift·apple
大熊猫侯佩1 天前
反抗军工程师的 “苹果智能” 实战指南:用本机基础模型打造 AI 利刃
ai编程·swift·apple
YungFan2 天前
iOS26适配指南之UIViewController
ios·swift