跳到主要内容

线程安全问题排查

问题

多线程访问共享数据导致偶发 Crash 或数据异常,如何排查?

答案

排查工具

工具用途
Thread Sanitizer (TSan)编译期检测数据竞争
Xcode Thread Checker检测非主线程操作 UI
Crash 堆栈多线程同时出现在同一数据结构

开启 TSan

Xcode → Scheme → Diagnostics → Thread Sanitizer ✅

常见场景及修复

// ❌ 多线程同时读写数组
var items: [String] = []
// Thread A: items.append("a")
// Thread B: let count = items.count // 💥 Crash

// ✅ 方案一:串行队列
private let queue = DispatchQueue(label: "com.app.items")
func addItem(_ item: String) {
queue.sync { items.append(item) }
}
func getItems() -> [String] {
queue.sync { items }
}

// ✅ 方案二:读写锁(并发读,互斥写)
private let queue = DispatchQueue(label: "com.app.items", attributes: .concurrent)
func addItem(_ item: String) {
queue.async(flags: .barrier) { self.items.append(item) }
}
func getItems() -> [String] {
queue.sync { items }
}

// ✅ 方案三:Swift Actor (推荐)
actor ItemStore {
private var items: [String] = []
func add(_ item: String) { items.append(item) }
func getAll() -> [String] { items }
}

常见面试问题

Q1: Actor 和传统锁的区别?

答案:Actor 是 Swift 语言级的并发隔离机制。所有访问自动转为 await,编译器保证同一时间只有一个任务访问 Actor 内部状态,无需手动加锁。消除了忘记加锁、死锁等问题。

相关链接