并发与锁的本质
为什么需要锁?
═══════════════════════════════════════════════════════════════════════════
并发问题的本质
═══════════════════════════════════════════════════════════════════════════
问题场景:两个线程同时对 count 进行 +1 操作
┌─────────────────────────────────────────────────────────────────────┐
│ 内存中的 count = 0 │
└─────────────────────────────────────────────────────────────────────┘
↑
┌────────────────────┴────────────────────┐
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ Thread A │ │ Thread B │
│ │ │ │
│ 1.读取count │ ←─ 同时执行 ─→ │ 1.读取count │
│ (得到0) │ │ (得到0) │
│ │ │ │
│ 2.计算0+1=1 │ │ 2.计算0+1=1 │
│ │ │ │
│ 3.写回count │ │ 3.写回count │
│ (写入1) │ │ (写入1) │
└─────────────┘ └─────────────┘
期望结果:count = 2
实际结果:count = 1 ← 数据竞争(Data Race)!
═══════════════════════════════════════════════════════════════════════════
问题根源:复合操作的非原子性
┌─────────────────────────────────────────────────────────────────────┐
│ count++ 的本质 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 高级语言: count++ │
│ ↓ │
│ CPU指令: 1. LOAD count → register (读取到寄存器) │
│ 2. ADD register, 1 (寄存器+1) │
│ 3. STORE register → count (写回内存) │
│ │
│ 三条指令之间可能被其他线程打断! │
│ │
└─────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
锁的本质
swift
/*
═══════════════════════════════════════════════════════════════════════════
锁的本质
═══════════════════════════════════════════════════════════════════════════
锁的核心作用:确保临界区代码的互斥执行
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 没有锁的情况: │
│ │
│ Thread A ████████████████░░░░░░░░░░████████████ │
│ Thread B ░░░░████████████████████████░░░░░░░░░░ │
│ ↑ │
│ 同时访问临界区,发生数据竞争 │
│ │
│ │
│ 有锁的情况: │
│ │
│ Thread A ████[临界区]████░░░░░░░░░░░░░░░░░░░░████ │
│ Thread B ░░░░░░░░░░░░░░░░[等待][临界区]░░░░░░░░░░ │
│ ↑ ↑ ↑ │
│ 加锁 等待 获得锁 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
锁的基本操作:
┌─────────────┬────────────────────────────────────────────────────────────┐
│ 操作 │ 说明 │
├─────────────┼────────────────────────────────────────────────────────────┤
│ 加锁 │ 尝试获取锁的所有权 │
│ (Lock) │ 如果锁被占用,线程进入等待状态 │
├─────────────┼────────────────────────────────────────────────────────────┤
│ 解锁 │ 释放锁的所有权 │
│ (Unlock) │ 唤醒等待的线程 │
├─────────────┼────────────────────────────────────────────────────────────┤
│ 尝试加锁 │ 尝试获取锁,立即返回结果 │
│ (TryLock) │ 不阻塞线程 │
└─────────────┴────────────────────────────────────────────────────────────┘
*/
锁的分类维度
═══════════════════════════════════════════════════════════════════════════
锁的分类维度
═══════════════════════════════════════════════════════════════════════════
1. 按等待方式分类
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 自旋锁(Spin Lock) 互斥锁(Mutex Lock) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ │ │ │ │
│ │ while(!获得锁) { │ │ if (!获得锁) { │ │
│ │ // 忙等待 │ │ 休眠(); │ │
│ │ // CPU空转 │ │ 等待唤醒(); │ │
│ │ } │ │ } │ │
│ │ │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ 优点:无上下文切换开销 优点:不消耗CPU │
│ 缺点:持续消耗CPU 缺点:有上下文切换开销 │
│ 适用:临界区极短 适用:临界区较长 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
2. 按可重入性分类
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 非递归锁 递归锁(Recursive Lock) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ │ │ │ │
│ │ 同一线程重复加锁 │ │ 同一线程可重复加锁 │ │
│ │ → 死锁! │ │ → 计数+1 │ │
│ │ │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
3. 按公平性分类
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 公平锁 非公平锁 │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ │ │ │ │
│ │ 先到先得 │ │ 允许插队 │ │
│ │ 按等待顺序获取锁 │ │ 新来的线程可能 │ │
│ │ │ │ 直接获得锁 │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ 优点:不会饿死 优点:吞吐量高 │
│ 缺点:吞吐量较低 缺点:可能饿死 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
4. 按读写方式分类
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 互斥锁 读写锁(RW Lock) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ │ │ │ │
│ │ 读/写都互斥 │ │ 读-读 可并发 │ │
│ │ 同时只有一个操作 │ │ 读-写 互斥 │ │
│ │ │ │ 写-写 互斥 │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
iOS 锁的全景图
iOS 中的锁总览
═══════════════════════════════════════════════════════════════════════════
iOS 锁的完整体系
═══════════════════════════════════════════════════════════════════════════
┌─────────────────┐
│ 锁的抽象层 │
└────────┬────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 自旋锁 │ │ 互斥锁 │ │ 其他锁 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ │ │
┌────┴────┐ ┌────────┼────────┐ ┌─────┴─────┐
│ │ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│OSSpinLock│ │atomic│ │pthread│ │NSLock│ │@sync │ │NSRec │ │NSCon │
│(已废弃)│ │标记 │ │_mutex│ │ │ │ │ │ursive│ │dition│
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
│ │ │ │ │ │
│ │ │ │ │ │
▼ │ │ │ │ │
┌──────┐ │ │ │ │ │
│os_ │ │ │ │ │ │
│unfair│ │ │ │ │ │
│_lock │ │ │ │ │ │
└──────┘ │ │ │ │ │
│ │ │ │ │
└────────┴────────┴────────┴───────────┘
│
▼
┌─────────────────────┐
│ GCD 信号量/队列 │
│ (DispatchSemaphore)│
│ (DispatchQueue) │
└─────────────────────┘
┌───────────────────────────────────────────────────────────────────────┐
│ 各锁特性速查表 │
├───────────────┬────────┬────────┬────────┬────────┬─────────────────┤
│ 锁类型 │ 等待方式│ 可递归 │ 条件等待│ 读写分离│ 推荐场景 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ os_unfair_lock│ 自旋 │ ❌ │ ❌ │ ❌ │ 极短临界区 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ pthread_mutex │ 互斥 │ ❌ │ ✅ │ ❌ │ 通用互斥 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ NSLock │ 互斥 │ ❌ │ ❌ │ ❌ │ OC环境简单互斥 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ NSRecursiveLock│互斥 │ ✅ │ ❌ │ ❌ │ 递归调用 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ NSCondition │ 互斥 │ ❌ │ ✅ │ ❌ │ 生产者-消费者 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ NSConditionLock│互斥 │ ❌ │ ✅ │ ❌ │ 状态依赖 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ pthread_rwlock│ 互斥 │ ❌ │ ❌ │ ✅ │ 读多写少 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│ @synchronized │ 互斥 │ ✅ │ ❌ │ ❌ │ OC便捷语法 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│DispatchSemaphore│互斥 │ ❌ │ ❌ │ ❌ │ GCD环境 │
├───────────────┼────────┼────────┼────────┼────────┼─────────────────┤
│DispatchQueue │ 互斥 │ ✅ │ ❌ │ ✅ │ GCD并发控制 │
└───────────────┴────────┴────────┴────────┴────────┴─────────────────┘
═══════════════════════════════════════════════════════════════════════════
自旋锁详解
自旋锁原理
═══════════════════════════════════════════════════════════════════════════
自旋锁工作原理
═══════════════════════════════════════════════════════════════════════════
自旋锁的核心:忙等待(Busy Waiting)
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 获取锁的过程: │
│ │
│ while (锁被占用) { │
│ // CPU 空转,不断检查锁状态 │
│ // 不会放弃 CPU 时间片 │
│ // 不会进入休眠 │
│ } │
│ // 获得锁,进入临界区 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
自旋锁 vs 互斥锁 的等待过程:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 自旋锁等待: │
│ │
│ Thread ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ ↑ 不断循环检查 ↑ 获得锁 ↑ 执行 ↑ 释放锁 │
│ │
│ CPU使用率 ████████████████████████████████████ │
│ 持续占用CPU │
│ │
│ │
│ 互斥锁等待: │
│ │
│ Thread ▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓ │
│ ↑尝试↑ 休眠(让出CPU) ↑唤醒↑执行 │
│ │
│ CPU使用率 ██░░░░░░░░░░░░░░░░░░░░░░░░░████ │
│ 休眠期间不占用CPU │
│ │
└─────────────────────────────────────────────────────────────────────────┘
适用场景分析:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ✅ 适合自旋锁的场景: │
│ • 临界区代码极短(几条指令) │
│ • 持有锁时间很短(纳秒~微秒级) │
│ • 多核CPU(其他核心可以继续工作) │
│ │
│ ❌ 不适合自旋锁的场景: │
│ • 临界区代码较长 │
│ • 持有锁时间较长 │
│ • 单核CPU(自旋会阻塞整个系统) │
│ • 持有锁的线程可能被抢占(优先级反转) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
OSSpinLock 的问题与 os_unfair_lock
swift
// MARK: - OSSpinLock 的优先级反转问题
/*
═══════════════════════════════════════════════════════════════════════════
OSSpinLock 优先级反转问题
═══════════════════════════════════════════════════════════════════════════
场景:低优先级线程持有锁,高优先级线程等待锁
时间线:
─────────────────────────────────────────────────────────────────────────→
高优先级线程(H): ░░░░░░░░░░░░[自旋等待锁]▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
↑ 一直占用CPU自旋
↑ 但无法获得锁
低优先级线程(L): [持有锁]░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
↑ 持有锁
↑ 但因优先级低,得不到CPU时间
↑ 无法执行完临界区并释放锁
问题:
• 高优先级线程自旋,占用CPU
• 低优先级线程得不到CPU时间,无法释放锁
• 高优先级线程永远等不到锁
• 系统陷入"活锁"状态
═══════════════════════════════════════════════════════════════════════════
*/
// ❌ OSSpinLock 已废弃,不要使用
/*
var spinLock = OS_SPINLOCK_INIT
OSSpinLockLock(&spinLock)
// 临界区
OSSpinLockUnlock(&spinLock)
*/
// MARK: - os_unfair_lock(推荐)
import os
/// os_unfair_lock 是 Apple 推荐的替代方案
/// 它解决了优先级反转问题
class UnfairLockDemo {
// 初始化锁
private var unfairLock = os_unfair_lock()
// 受保护的数据
private var _value: Int = 0
var value: Int {
get {
os_unfair_lock_lock(&unfairLock)
defer { os_unfair_lock_unlock(&unfairLock) }
return _value
}
set {
os_unfair_lock_lock(&unfairLock)
_value = newValue
os_unfair_lock_unlock(&unfairLock)
}
}
/// 尝试加锁(非阻塞)
func tryLockDemo() {
if os_unfair_lock_trylock(&unfairLock) {
// 成功获得锁
defer { os_unfair_lock_unlock(&unfairLock) }
// 临界区代码
} else {
// 未能获得锁
print("锁被占用")
}
}
}
/*
os_unfair_lock 特点:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ✅ 优点: │
│ • 解决了优先级反转问题 │
│ • 性能极高(接近 OSSpinLock) │
│ • 内存占用小(只需要一个 32位 整数) │
│ • Apple 推荐使用 │
│ │
│ ❌ 限制: │
│ • 不可递归(同一线程重复加锁会死锁) │
│ • 必须在同一线程加锁和解锁 │
│ • 不支持条件等待 │
│ • iOS 10+ / macOS 10.12+ │
│ │
│ ⚠️ 注意: │
│ • "unfair"表示不保证公平性(不按等待顺序分配锁) │
│ • 不公平设计是为了更高的性能 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
*/
封装线程安全的自旋锁
swift
// MARK: - 封装 os_unfair_lock
import os
/// 线程安全的自旋锁封装
public final class UnfairLock: @unchecked Sendable {
private var _lock: os_unfair_lock
public init() {
_lock = os_unfair_lock()
}
/// 加锁
public func lock() {
os_unfair_lock_lock(&_lock)
}
/// 解锁
public func unlock() {
os_unfair_lock_unlock(&_lock)
}
/// 尝试加锁
public func tryLock() -> Bool {
return os_unfair_lock_trylock(&_lock)
}
/// 在锁保护下执行闭包
@discardableResult
public func withLock<T>(_ body: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try body()
}
/// 尝试在锁保护下执行闭包
@discardableResult
public func withLockIfAvailable<T>(_ body: () throws -> T) rethrows -> T? {
guard tryLock() else { return nil }
defer { unlock() }
return try body()
}
}
// MARK: - 使用示例
class ThreadSafeCounter {
private let lock = UnfairLock()
private var _count = 0
var count: Int {
lock.withLock { _count }
}
func increment() {
lock.withLock {
_count += 1
}
}
func decrement() {
lock.withLock {
_count -= 1
}
}
/// 原子地获取并增加
func getAndIncrement() -> Int {
lock.withLock {
let current = _count
_count += 1
return current
}
}
}
// MARK: - 属性包装器
@propertyWrapper
public final class Locked<Value> {
private var value: Value
private let lock = UnfairLock()
public init(wrappedValue: Value) {
self.value = wrappedValue
}
public var wrappedValue: Value {
get { lock.withLock { value } }
set { lock.withLock { value = newValue } }
}
/// 提供对锁的直接访问(用于复合操作)
public var projectedValue: UnfairLock {
return lock
}
/// 执行复合操作
public func mutate<T>(_ mutation: (inout Value) throws -> T) rethrows -> T {
return try lock.withLock {
try mutation(&value)
}
}
}
// 使用属性包装器
class Example {
@Locked var items: [String] = []
func addItem(_ item: String) {
// 简单操作直接赋值
items.append(item) // 自动加锁
}
func complexOperation() {
// 复合操作使用 mutate
_items.mutate { items in
if items.isEmpty {
items.append("default")
}
items.append("new item")
}
}
}
互斥锁详解
pthread_mutex
swift
// MARK: - pthread_mutex 详解
import Foundation
/*
═══════════════════════════════════════════════════════════════════════════
pthread_mutex 结构
═══════════════════════════════════════════════════════════════════════════
pthread_mutex 是 POSIX 线程库提供的互斥锁,是最基础的互斥锁实现。
锁的内部结构(简化):
┌─────────────────────────────────────────────────────────────────────────┐
│ pthread_mutex_t │
├─────────────────────────────────────────────────────────────────────────┤
│ owner │ 持有锁的线程ID │
│ count │ 递归计数(仅递归锁) │
│ waiters │ 等待队列 │
│ type │ 锁类型(普通/递归/错误检查) │
└─────────────────────────────────────────────────────────────────────────┘
工作流程:
加锁 (pthread_mutex_lock):
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. 检查锁是否被占用 │
│ ├── 未占用:设置owner为当前线程,返回成功 │
│ └── 已占用: │
│ ├── 是当前线程(递归锁):count++,返回成功 │
│ └── 是其他线程:加入等待队列,线程休眠 │
└─────────────────────────────────────────────────────────────────────────┘
解锁 (pthread_mutex_unlock):
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. 检查当前线程是否是owner │
│ 2. count--(递归锁) │
│ 3. 如果count==0,清除owner,唤醒等待队列中的线程 │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
*/
class PthreadMutexDemo {
// MARK: - 普通互斥锁
/// 普通互斥锁示例
func normalMutexDemo() {
var mutex = pthread_mutex_t()
var attr = pthread_mutexattr_t()
// 初始化属性
pthread_mutexattr_init(&attr)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)
// 初始化锁
pthread_mutex_init(&mutex, &attr)
// 销毁属性(不再需要)
pthread_mutexattr_destroy(&attr)
// 使用锁
pthread_mutex_lock(&mutex)
// 临界区代码
pthread_mutex_unlock(&mutex)
// 销毁锁
pthread_mutex_destroy(&mutex)
}
// MARK: - 递归互斥锁
/// 递归互斥锁示例
func recursiveMutexDemo() {
var mutex = pthread_mutex_t()
var attr = pthread_mutexattr_t()
pthread_mutexattr_init(&attr)
// 设置为递归锁类型
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
pthread_mutex_init(&mutex, &attr)
pthread_mutexattr_destroy(&attr)
// 同一线程可以多次加锁
pthread_mutex_lock(&mutex)
pthread_mutex_lock(&mutex) // 不会死锁
// 临界区
pthread_mutex_unlock(&mutex)
pthread_mutex_unlock(&mutex) // 需要解锁相同次数
pthread_mutex_destroy(&mutex)
}
// MARK: - 错误检查互斥锁
/// 错误检查互斥锁示例
func errorCheckMutexDemo() {
var mutex = pthread_mutex_t()
var attr = pthread_mutexattr_t()
pthread_mutexattr_init(&attr)
// 设置为错误检查类型
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)
pthread_mutex_init(&mutex, &attr)
pthread_mutexattr_destroy(&attr)
pthread_mutex_lock(&mutex)
// 同一线程再次加锁会返回错误(而不是死锁)
let result = pthread_mutex_lock(&mutex)
if result == EDEADLK {
print("检测到死锁!")
}
pthread_mutex_unlock(&mutex)
pthread_mutex_destroy(&mutex)
}
// MARK: - trylock 非阻塞加锁
/// 非阻塞加锁示例
func tryLockDemo() {
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
// 尝试加锁,立即返回
let result = pthread_mutex_trylock(&mutex)
if result == 0 {
// 成功获得锁
defer { pthread_mutex_unlock(&mutex) }
// 临界区代码
} else if result == EBUSY {
// 锁被占用
print("锁正在被使用")
}
pthread_mutex_destroy(&mutex)
}
}
// MARK: - pthread_mutex 封装
public final class Mutex {
private var mutex = pthread_mutex_t()
public init(recursive: Bool = false) {
var attr = pthread_mutexattr_t()
pthread_mutexattr_init(&attr)
if recursive {
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
} else {
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)
}
pthread_mutex_init(&mutex, &attr)
pthread_mutexattr_destroy(&attr)
}
deinit {
pthread_mutex_destroy(&mutex)
}
public func lock() {
pthread_mutex_lock(&mutex)
}
public func unlock() {
pthread_mutex_unlock(&mutex)
}
public func tryLock() -> Bool {
return pthread_mutex_trylock(&mutex) == 0
}
@discardableResult
public func withLock<T>(_ body: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try body()
}
}
NSLock
swift
// MARK: - NSLock 详解
/*
═══════════════════════════════════════════════════════════════════════════
NSLock 内部结构
═══════════════════════════════════════════════════════════════════════════
NSLock 是 pthread_mutex 的 Objective-C 封装。
源码简化(来自 swift-corelibs-foundation):
open class NSLock: NSObject, NSLocking {
internal var mutex = pthread_mutex_t()
public override init() {
super.init()
pthread_mutex_init(&mutex, nil)
}
deinit {
pthread_mutex_destroy(&mutex)
}
open func lock() {
pthread_mutex_lock(&mutex)
}
open func unlock() {
pthread_mutex_unlock(&mutex)
}
open func `try`() -> Bool {
return pthread_mutex_trylock(&mutex) == 0
}
open func lock(before limit: Date) -> Bool {
// 带超时的加锁
}
}
═══════════════════════════════════════════════════════════════════════════
*/
class NSLockDemo {
private let lock = NSLock()
private var sharedResource = 0
// MARK: - 基本使用
func basicUsage() {
lock.lock()
defer { lock.unlock() }
// 临界区代码
sharedResource += 1
}
// MARK: - try() 非阻塞加锁
func tryLockUsage() {
if lock.try() {
defer { lock.unlock() }
// 成功获得锁
sharedResource += 1
} else {
// 锁被占用
print("无法获得锁")
}
}
// MARK: - 带超时的加锁
func lockWithTimeout() {
let timeout = Date().addingTimeInterval(1.0) // 1秒超时
if lock.lock(before: timeout) {
defer { lock.unlock() }
// 在超时前获得了锁
sharedResource += 1
} else {
// 超时未能获得锁
print("加锁超时")
}
}
// MARK: - 使用 name 属性进行调试
func debugUsage() {
lock.name = "com.example.sharedResourceLock"
lock.lock()
// 调试时可以看到锁的名称
lock.unlock()
}
}
// MARK: - NSLock 扩展
extension NSLock {
/// 在锁保护下执行闭包
@discardableResult
func withLock<T>(_ body: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try body()
}
/// 尝试在锁保护下执行闭包
@discardableResult
func withLockIfAvailable<T>(_ body: () throws -> T) rethrows -> T? {
guard `try`() else { return nil }
defer { unlock() }
return try body()
}
}
// MARK: - NSLock vs os_unfair_lock 选择
/*
┌─────────────────────────────────────────────────────────────────────────┐
│ NSLock vs os_unfair_lock │
├───────────────────┬─────────────────────┬───────────────────────────────┤
│ 特性 │ os_unfair_lock │ NSLock │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 底层实现 │ 自旋 + 休眠混合 │ pthread_mutex(纯互斥) │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 性能 │ 更高 │ 稍低 │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 超时支持 │ ❌ │ ✅ lock(before:) │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 名称/调试 │ ❌ │ ✅ name 属性 │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 面向对象 │ ❌ C API │ ✅ NSObject 子类 │
├───────────────────┼─────────────────────┼───────────────────────────────┤
│ 使用场景 │ 高性能要求 │ 需要超时/调试支持 │
└───────────────────┴─────────────────────┴───────────────────────────────┘
*/
@synchronized
swift
// MARK: - @synchronized 详解
/*
═══════════════════════════════════════════════════════════════════════════
@synchronized 原理
═══════════════════════════════════════════════════════════════════════════
@synchronized 是 Objective-C 的语法糖,编译后会转换为:
@synchronized(obj) {
// 代码
}
↓ 编译为 ↓
@try {
objc_sync_enter(obj);
// 代码
} @finally {
objc_sync_exit(obj);
}
objc_sync_enter 内部原理:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 1. 以对象地址为 key,在全局哈希表中查找/创建 SyncData │
│ │
│ struct SyncData { │
│ id object; // 关联的对象 │
│ recursive_mutex_t mutex; // 递归互斥锁 │
│ int threadCount; // 使用此锁的线程数 │
│ SyncData* next; // 链表下一个节点 │
│ }; │
│ │
│ 2. 对 SyncData 中的 mutex 加锁 │
│ │
│ 全局哈希表结构: │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ hash(objA) → [SyncData(objA)] → [SyncData(objX)] → nil │ │
│ │ hash(objB) → [SyncData(objB)] → nil │ │
│ │ hash(objC) → [SyncData(objC)] → [SyncData(objY)] → nil │ │
│ │ ... │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
*/
// Objective-C 中的使用
/*
@synchronized (self) {
// 临界区代码
}
*/
// MARK: - Swift 中模拟 @synchronized
/// Swift 中的 synchronized 实现
func synchronized<T>(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
// 使用示例
class SynchronizedDemo {
private var _value = 0
var value: Int {
get {
return synchronized(self) {
_value
}
}
set {
synchronized(self) {
_value = newValue
}
}
}
func increment() {
synchronized(self) {
_value += 1
}
}
}
// MARK: - @synchronized 的优缺点
/*
┌─────────────────────────────────────────────────────────────────────────┐
│ @synchronized 优缺点 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ✅ 优点: │
│ • 语法简洁,使用方便 │
│ • 自动处理异常,保证解锁 │
│ • 支持递归(同一线程可重入) │
│ • 不需要手动创建锁对象 │
│ │
│ ❌ 缺点: │
│ • 性能较低(哈希表查找 + 递归锁开销) │
│ • 依赖对象生命周期(对象释放后锁失效) │
│ • 无法设置超时 │
│ • 不同对象可能哈希冲突,共用同一个锁 │
│ │
│ ⚠️ 注意事项: │
│ • 不要使用 self 作为锁对象(可能被子类覆盖) │
│ • 不要使用常量对象(如 @"string") │
│ • 建议使用专门的锁对象 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
*/
// 推荐用法:使用专门的锁对象
class BetterSynchronizedDemo {
private let lockObject = NSObject() // 专门的锁对象
private var _data: [String] = []
func addData(_ item: String) {
synchronized(lockObject) {
_data.append(item)
}
}
func getData() -> [String] {
synchronized(lockObject) {
return _data
}
}
}
递归锁详解
递归锁原理
═══════════════════════════════════════════════════════════════════════════
递归锁工作原理
═══════════════════════════════════════════════════════════════════════════
递归锁允许同一线程多次获取锁,不会死锁。
内部结构:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ RecursiveLock { │
│ owner: ThreadID // 持有锁的线程 │
│ count: Int // 重入计数 │
│ waitQueue: [Thread] // 等待队列 │
│ } │
│ │
└─────────────────────────────────────────────────────────────────────────┘
加锁流程:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ lock() { │
│ currentThread = getCurrentThread() │
│ │
│ if (owner == nil) { │
│ owner = currentThread │
│ count = 1 │
│ return SUCCESS │
│ } │
│ │
│ if (owner == currentThread) { │
│ count++ // 重入,计数+1 │
│ return SUCCESS │
│ } │
│ │
│ // 其他线程持有锁 │
│ waitQueue.add(currentThread) │
│ sleep() // 休眠等待 │
│ } │
│ │
└─────────────────────────────────────────────────────────────────────────┘
解锁流程:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ unlock() { │
│ if (owner != currentThread) { │
│ return ERROR // 非持有者不能解锁 │
│ } │
│ │
│ count-- │
│ │
│ if (count == 0) { │
│ owner = nil │
│ if (!waitQueue.isEmpty) { │
│ nextThread = waitQueue.removeFirst() │
│ wakeup(nextThread) // 唤醒等待线程 │
│ } │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────────────────┘
示例场景:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ Thread A: │
│ │
│ recursiveLock.lock() // count = 1, owner = A │
│ │ │
│ ├── recursiveLock.lock() // count = 2, owner = A (重入) │
│ │ │ │
│ │ ├── recursiveLock.lock() // count = 3 │
│ │ │ └── // 临界区代码 │
│ │ │ │
│ │ └── recursiveLock.unlock() // count = 2 │
│ │ │
│ └── recursiveLock.unlock() // count = 1 │
│ │
│ recursiveLock.unlock() // count = 0, owner = nil │
│ // 锁完全释放 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
NSRecursiveLock
swift
// MARK: - NSRecursiveLock 使用
class NSRecursiveLockDemo {
private let recursiveLock = NSRecursiveLock()
private var data: [String] = []
// MARK: - 递归调用场景
/// 递归方法需要递归锁
func processData(_ items: [String]) {
recursiveLock.lock()
defer { recursiveLock.unlock() }
for item in items {
if item.hasPrefix("group:") {
// 递归处理子组
let subItems = parseSubItems(item)
processData(subItems) // 递归调用,需要递归锁!
} else {
data.append(item)
}
}
}
private func parseSubItems(_ item: String) -> [String] {
// 解析子项
return []
}
// MARK: - 方法相互调用场景
func methodA() {
recursiveLock.lock()
defer { recursiveLock.unlock() }
// 某些逻辑
methodB() // 调用另一个加锁方法
}
func methodB() {
recursiveLock.lock()
defer { recursiveLock.unlock() }
// 某些逻辑
// 如果使用普通锁,这里会死锁
}
// MARK: - 实际场景:树形结构遍历
class TreeNode {
var value: Int
var children: [TreeNode] = []
init(value: Int) {
self.value = value
}
}
private var visitedNodes: Set<Int> = []
/// 线程安全的树遍历
func traverseTree(_ node: TreeNode?) {
recursiveLock.lock()
defer { recursiveLock.unlock() }
guard let node = node else { return }
visitedNodes.insert(node.value)
for child in node.children {
traverseTree(child) // 递归调用
}
}
}
// MARK: - 递归锁封装
public final class RecursiveLock {
private let lock = NSRecursiveLock()
public init() {}
public func lock() {
self.lock.lock()
}
public func unlock() {
self.lock.unlock()
}
public func tryLock() -> Bool {
return lock.try()
}
@discardableResult
public func withLock<T>(_ body: () throws -> T) rethrows -> T {
lock.lock()
defer { lock.unlock() }
return try body()
}
}
递归锁的注意事项
swift
// MARK: - 递归锁的陷阱与最佳实践
/*
═══════════════════════════════════════════════════════════════════════════
递归锁使用注意事项
═══════════════════════════════════════════════════════════════════════════
⚠️ 陷阱1:lock/unlock 不配对
─────────────────────────────────────────────────────────────────────────
*/
class RecursiveLockTrap1 {
let lock = NSRecursiveLock()
// ❌ 错误:lock 和 unlock 次数不匹配
func badExample() {
lock.lock()
lock.lock()
// 临界区
lock.unlock()
// 少了一次 unlock!锁永远不会释放
}
// ✅ 正确:使用 defer 确保配对
func goodExample() {
lock.lock()
defer { lock.unlock() }
lock.lock()
defer { lock.unlock() }
// 临界区
}
}
/*
⚠️ 陷阱2:过度使用递归锁
─────────────────────────────────────────────────────────────────────────
*/
class RecursiveLockTrap2 {
let recursiveLock = NSRecursiveLock()
// ❌ 不好的设计:不必要地使用递归锁
func badDesign() {
recursiveLock.lock()
defer { recursiveLock.unlock() }
helperMethod()
}
func helperMethod() {
recursiveLock.lock() // 真的需要吗?
defer { recursiveLock.unlock() }
// ...
}
// ✅ 更好的设计:分离内部方法
let normalLock = NSLock()
func betterDesign() {
normalLock.lock()
defer { normalLock.unlock() }
// 内部方法不加锁
internalHelperMethod()
}
// 私有方法,假定调用者已持有锁
private func internalHelperMethod() {
// 不需要加锁
}
}
/*
⚠️ 陷阱3:递归锁性能较低
─────────────────────────────────────────────────────────────────────────
*/
/*
┌─────────────────────────────────────────────────────────────────────────┐
│ 递归锁 vs 普通锁 性能对比 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 递归锁额外开销: │
│ • 检查当前线程是否是 owner │
│ • 维护重入计数 │
│ • 每次 lock/unlock 都要更新计数 │
│ │
│ 性能建议: │
│ • 如果不需要递归,使用普通锁 │
│ • 重构代码避免递归锁的需求 │
│ • 将需要锁保护的部分提取为内部无锁方法 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
*/
// MARK: - 最佳实践:避免递归锁
class AvoidRecursiveLock {
private let lock = NSLock()
private var items: [String] = []
// ✅ 推荐:公开方法加锁,内部方法不加锁
func addItem(_ item: String) {
lock.lock()
defer { lock.unlock() }
_addItem(item)
}
func addItems(_ items: [String]) {
lock.lock()
defer { lock.unlock() }
for item in items {
_addItem(item) // 调用内部方法,不会重复加锁
}
}
// 私有方法,不加锁,假定调用者已持有锁
private func _addItem(_ item: String) {
items.append(item)
// 可以安全地调用其他内部方法
_notifyObservers()
}
private func _notifyObservers() {
// 不加锁
}
}
读写锁详解
读写锁原理
═══════════════════════════════════════════════════════════════════════════
读写锁工作原理
═══════════════════════════════════════════════════════════════════════════
读写锁的核心思想:读操作可以并发,写操作需要独占
┌─────────────────────────────────────────────────────────────────────────┐
│ 访问规则矩阵 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ │ 无锁 │ 读锁 │ 写锁 │ │
│ ────────────┼──────────┼──────────┼──────────┤ │
│ 请求读锁 │ ✅ │ ✅ │ ❌ │ │
│ ────────────┼──────────┼──────────┼──────────┤ │
│ 请求写锁 │ ✅ │ ❌ │ ❌ │ │
│ │
│ ✅ = 立即获得 ❌ = 等待 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
读写锁状态图:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ │
│ ┌────────→│ 空闲 │←────────┐ │
│ │ └──────┬──────┘ │ │
│ │ │ │ │
│ 解除写锁 请求读锁/写锁 解除所有读锁 │
│ │ │ │ │
│ │ ┌────────┴────────┐ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ ┌──────┴─────────┐ ┌──────────────┴──┐ │
│ │ 写锁定 │ │ 读锁定 │ │
│ │ (1个写者) │ │ (N个读者) │ │
│ └────────────────┘ └─────────────────┘ │
│ ↑ │ ↑ │
│ │ │ │ │
│ │ ←──────────────┘ │ │
│ │ 所有读者释放后 │ │
│ │ 才能获得写锁 └──── 新读者加入 │
│ │ │
│ └──────────────────── 写锁释放后读者可进入 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
读写锁并发示例:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 时间线 ─────────────────────────────────────────────────────────────→│
│ │
│ Reader1 ═══════════════════ │
│ Reader2 ═══════════════════ │
│ Reader3 ═══════════════ ════════ │
│ Writer1 ████████ │
│ Reader4 ════════════════ │
│ Writer2 ████ │
│ │
│ ═══ 读锁(可并发) │
│ ███ 写锁(独占) │
│ │
│ 注意:Writer1 必须等待所有 Reader 释放才能获得写锁 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
pthread_rwlock
swift
// MARK: - pthread_rwlock 使用
import Foundation
class PthreadRWLockDemo {
private var rwlock = pthread_rwlock_t()
private var sharedData: [String: Any] = [:]
init() {
pthread_rwlock_init(&rwlock, nil)
}
deinit {
pthread_rwlock_destroy(&rwlock)
}
// MARK: - 读操作(可并发)
func read(_ key: String) -> Any? {
pthread_rwlock_rdlock(&rwlock) // 读锁
defer { pthread_rwlock_unlock(&rwlock) }
return sharedData[key]
}
func readAll() -> [String: Any] {
pthread_rwlock_rdlock(&rwlock)
defer { pthread_rwlock_unlock(&rwlock) }
return sharedData
}
// MARK: - 写操作(独占)
func write(_ key: String, value: Any) {
pthread_rwlock_wrlock(&rwlock) // 写锁
defer { pthread_rwlock_unlock(&rwlock) }
sharedData[key] = value
}
func remove(_ key: String) {
pthread_rwlock_wrlock(&rwlock)
defer { pthread_rwlock_unlock(&rwlock) }
sharedData.removeValue(forKey: key)
}
// MARK: - trylock 变体
func tryRead(_ key: String) -> Any? {
guard pthread_rwlock_tryrdlock(&rwlock) == 0 else {
return nil // 无法获得读锁
}
defer { pthread_rwlock_unlock(&rwlock) }
return sharedData[key]
}
func tryWrite(_ key: String, value: Any) -> Bool {
guard pthread_rwlock_trywrlock(&rwlock) == 0 else {
return false // 无法获得写锁
}
defer { pthread_rwlock_unlock(&rwlock) }
sharedData[key] = value
return true
}
}
// MARK: - 读写锁封装
public final class ReadWriteLock {
private var rwlock = pthread_rwlock_t()
public init() {
pthread_rwlock_init(&rwlock, nil)
}
deinit {
pthread_rwlock_destroy(&rwlock)
}
/// 读锁
public func readLock() {
pthread_rwlock_rdlock(&rwlock)
}
/// 写锁
public func writeLock() {
pthread_rwlock_wrlock(&rwlock)
}
/// 解锁(读写通用)
public func unlock() {
pthread_rwlock_unlock(&rwlock)
}
/// 尝试获得读锁
public func tryReadLock() -> Bool {
return pthread_rwlock_tryrdlock(&rwlock) == 0
}
/// 尝试获得写锁
public func tryWriteLock() -> Bool {
return pthread_rwlock_trywrlock(&rwlock) == 0
}
/// 在读锁保护下执行
@discardableResult
public func withReadLock<T>(_ body: () throws -> T) rethrows -> T {
readLock()
defer { unlock() }
return try body()
}
/// 在写锁保护下执行
@discardableResult
public func withWriteLock<T>(_ body: () throws -> T) rethrows -> T {
writeLock()
defer { unlock() }
return try body()
}
}
// MARK: - 使用示例:线程安全的缓存
final class ThreadSafeCache<Key: Hashable, Value> {
private var cache: [Key: Value] = [:]
private let lock = ReadWriteLock()
/// 读取(并发安全)
func get(_ key: Key) -> Value? {
lock.withReadLock {
cache[key]
}
}
/// 写入(独占)
func set(_ key: Key, value: Value) {
lock.withWriteLock {
cache[key] = value
}
}
/// 删除(独占)
func remove(_ key: Key) {
lock.withWriteLock {
cache.removeValue(forKey: key)
}
}
/// 读取所有键(并发安全)
var keys: [Key] {
lock.withReadLock {
Array(cache.keys)
}
}
/// 缓存大小(并发安全)
var count: Int {
lock.withReadLock {
cache.count
}
}
/// 清空(独占)
func clear() {
lock.withWriteLock {
cache.removeAll()
}
}
/// 批量更新(独占)
func update(_ updates: [Key: Value]) {
lock.withWriteLock {
for (key, value) in updates {
cache[key] = value
}
}
}
}
GCD 实现读写锁
swift
// MARK: - 使用 GCD 实现读写锁
final class GCDReadWriteLock<Value> {
private var _value: Value
private let queue: DispatchQueue
init(_ value: Value, label: String = "com.rwlock.queue") {
self._value = value
// 使用并发队列
self.queue = DispatchQueue(label: label, attributes: .concurrent)
}
/// 读取(并发)
var value: Value {
queue.sync {
_value
}
}
/// 写入(barrier 独占)
func mutate(_ transform: (inout Value) -> Void) {
queue.sync(flags: .barrier) {
transform(&_value)
}
}
/// 异步写入
func mutateAsync(_ transform: @escaping (inout Value) -> Void) {
queue.async(flags: .barrier) {
transform(&self._value)
}
}
}
/*
═══════════════════════════════════════════════════════════════════════════
GCD Barrier 原理
═══════════════════════════════════════════════════════════════════════════
并发队列 + Barrier 实现读写锁:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 并发队列正常状态: │
│ │
│ Task1 ════════════ │
│ Task2 ════════════ │
│ Task3 ════════════ │
│ ↑ 可并发执行 │
│ │
│ │
│ 使用 Barrier 的任务: │
│ │
│ Task1 ════════ │
│ Task2 ════════ │
│ Barrier ░░░░██████████░░░░ │
│ Task4 ════════ │
│ Task5 ════════ │
│ ↑ ↑ ↑ ↑ │
│ 等待 独占执行 完成 后续任务继续并发 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
*/
// MARK: - 使用示例
class GCDRWLockExample {
// 线程安全的字典
private let storage = GCDReadWriteLock<[String: Any]>([:])
func read(_ key: String) -> Any? {
return storage.value[key]
}
func write(_ key: String, value: Any) {
storage.mutate { dict in
dict[key] = value
}
}
// 异步批量写入
func batchWrite(_ items: [String: Any]) {
storage.mutateAsync { dict in
for (key, value) in items {
dict[key] = value
}
}
}
}
// MARK: - 属性包装器版本
@propertyWrapper
final class RWLocked<Value> {
private var value: Value
private let queue: DispatchQueue
init(wrappedValue: Value) {
self.value = wrappedValue
self.queue = DispatchQueue(
label: "com.rwlocked.\(UUID().uuidString)",
attributes: .concurrent
)
}
var wrappedValue: Value {
get {
queue.sync { value }
}
set {
queue.sync(flags: .barrier) {
value = newValue
}
}
}
```swift
var projectedValue: RWLocked<Value> {
return self
}
/// 执行读操作
func read<T>(_ transform: (Value) -> T) -> T {
queue.sync {
transform(value)
}
}
/// 执行写操作
func write(_ transform: (inout Value) -> Void) {
queue.sync(flags: .barrier) {
transform(&value)
}
}
}
// 使用属性包装器
class ConfigManager {
@RWLocked private var settings: [String: Any] = [:]
func getSetting(_ key: String) -> Any? {
return _settings.read { $0[key] }
}
func setSetting(_ key: String, value: Any) {
_settings.write { $0[key] = value }
}
func updateSettings(_ updates: [String: Any]) {
_settings.write { settings in
for (key, value) in updates {
settings[key] = value
}
}
}
}
条件锁详解
条件变量原理
═══════════════════════════════════════════════════════════════════════════
条件变量工作原理
═══════════════════════════════════════════════════════════════════════════
条件变量:让线程等待某个条件成立
典型场景:生产者-消费者模型
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ Producer Buffer Consumer │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ │ produce │ [ ][ ]│ consume │ │ │
│ │ P1 │ ────────────→ │ [X][X]│ ────────────→ │ C1 │ │
│ │ │ │ [X][ ]│ │ │ │
│ └───────┘ └───────┘ └───────┘ │
│ │ │
│ │ │
│ 问题: │ │
│ • Buffer 满了,生产者怎么办? │ │
│ • Buffer 空了,消费者怎么办? │ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
条件变量解决方案:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 生产者逻辑: 消费者逻辑: │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ lock(mutex) │ │ lock(mutex) │ │
│ │ │ │ │ │
│ │ while (buffer满) { │ │ while (buffer空) { │ │
│ │ wait(notFull) │ │ wait(notEmpty) │ │
│ │ // 释放锁,休眠 │ │ // 释放锁,休眠 │ │
│ │ // 被唤醒后重新加锁 │ │ // 被唤醒后重新加锁 │ │
│ │ } │ │ } │ │
│ │ │ │ │ │
│ │ buffer.add(item) │ │ item = buffer.remove() │ │
│ │ │ │ │ │
│ │ signal(notEmpty) │ │ signal(notFull) │ │
│ │ // 唤醒等待的消费者 │ │ // 唤醒等待的生产者 │ │
│ │ │ │ │ │
│ │ unlock(mutex) │ │ unlock(mutex) │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
wait() 操作的原子性(关键!):
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ condition.wait() 内部执行: │
│ │
│ 1. 原子地:释放 mutex + 加入等待队列 + 进入休眠 │
│ ↑ 这三步必须原子执行,否则会丢失信号 │
│ │
│ 2. 被 signal/broadcast 唤醒 │
│ │
│ 3. 原子地:从等待队列移除 + 重新获取 mutex │
│ │
│ 4. wait() 返回 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
signal vs broadcast:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ signal() - 唤醒一个等待的线程 │
│ broadcast() - 唤醒所有等待的线程 │
│ │
│ ┌─────────────────┐ │
│ │ 等待队列 │ │
│ │ [T1] [T2] [T3] │ │
│ └────────┬────────┘ │
│ │ │
│ signal() │ broadcast() │
│ ↓ │ ↓ │
│ 唤醒 T1 唤醒 T1, T2, T3 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
NSCondition
swift
// MARK: - NSCondition 使用
class NSConditionDemo {
private let condition = NSCondition()
private var buffer: [Int] = []
private let maxBufferSize = 5
// MARK: - 生产者-消费者示例
/// 生产者
func produce(_ item: Int) {
condition.lock()
defer { condition.unlock() }
// 等待缓冲区有空间
while buffer.count >= maxBufferSize {
print("缓冲区满,生产者等待...")
condition.wait() // 释放锁并等待
}
buffer.append(item)
print("生产: \(item), 缓冲区: \(buffer)")
// 通知消费者
condition.signal()
}
/// 消费者
func consume() -> Int {
condition.lock()
defer { condition.unlock() }
// 等待缓冲区有数据
while buffer.isEmpty {
print("缓冲区空,消费者等待...")
condition.wait()
}
let item = buffer.removeFirst()
print("消费: \(item), 缓冲区: \(buffer)")
// 通知生产者
condition.signal()
return item
}
// MARK: - 带超时的等待
func consumeWithTimeout(timeout: TimeInterval) -> Int? {
condition.lock()
defer { condition.unlock() }
let deadline = Date().addingTimeInterval(timeout)
while buffer.isEmpty {
// 带超时的等待
if !condition.wait(until: deadline) {
print("等待超时")
return nil
}
}
return buffer.removeFirst()
}
// MARK: - 广播通知所有等待者
func clear() {
condition.lock()
defer { condition.unlock() }
buffer.removeAll()
// 唤醒所有等待的线程
condition.broadcast()
}
}
// MARK: - 完整的线程安全队列
final class BlockingQueue<T> {
private var queue: [T] = []
private let condition = NSCondition()
private let maxSize: Int
private var isClosed = false
init(maxSize: Int = Int.max) {
self.maxSize = maxSize
}
/// 入队(阻塞直到有空间)
func enqueue(_ item: T) throws {
condition.lock()
defer { condition.unlock() }
while queue.count >= maxSize && !isClosed {
condition.wait()
}
guard !isClosed else {
throw QueueError.closed
}
queue.append(item)
condition.signal()
}
/// 出队(阻塞直到有元素)
func dequeue() throws -> T {
condition.lock()
defer { condition.unlock() }
while queue.isEmpty && !isClosed {
condition.wait()
}
guard !queue.isEmpty else {
throw QueueError.closed
}
let item = queue.removeFirst()
condition.signal()
return item
}
/// 尝试出队(非阻塞)
func tryDequeue() -> T? {
condition.lock()
defer { condition.unlock() }
if queue.isEmpty {
return nil
}
let item = queue.removeFirst()
condition.signal()
return item
}
/// 带超时的出队
func dequeue(timeout: TimeInterval) throws -> T? {
condition.lock()
defer { condition.unlock() }
let deadline = Date().addingTimeInterval(timeout)
while queue.isEmpty && !isClosed {
if !condition.wait(until: deadline) {
return nil // 超时
}
}
guard !queue.isEmpty else {
throw QueueError.closed
}
let item = queue.removeFirst()
condition.signal()
return item
}
/// 关闭队列
func close() {
condition.lock()
defer { condition.unlock() }
isClosed = true
condition.broadcast() // 唤醒所有等待的线程
}
/// 当前大小
var count: Int {
condition.lock()
defer { condition.unlock() }
return queue.count
}
enum QueueError: Error {
case closed
}
}
NSConditionLock
swift
// MARK: - NSConditionLock 使用
/*
═══════════════════════════════════════════════════════════════════════════
NSConditionLock 原理
═══════════════════════════════════════════════════════════════════════════
NSConditionLock = NSCondition + 条件值
可以根据条件值来决定是否获得锁,非常适合状态机场景。
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ NSConditionLock 内部: │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ condition: NSCondition // 条件变量 │ │
│ │ conditionValue: Int // 条件值 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ lock(whenCondition: 2) │
│ ↓ │
│ 等待 conditionValue == 2 时才获得锁 │
│ │
│ unlock(withCondition: 3) │
│ ↓ │
│ 释放锁,并将 conditionValue 设为 3 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
*/
class NSConditionLockDemo {
// 定义状态
enum State: Int {
case idle = 0
case dataReady = 1
case processing = 2
case completed = 3
}
private let lock = NSConditionLock(condition: State.idle.rawValue)
private var data: String?
// MARK: - 状态机示例
/// 阶段1:准备数据
func prepareData() {
// 等待 idle 状态
lock.lock(whenCondition: State.idle.rawValue)
defer { lock.unlock(withCondition: State.dataReady.rawValue) }
// 准备数据
data = "Hello, World!"
print("数据已准备")
}
/// 阶段2:处理数据
func processData() {
// 等待 dataReady 状态
lock.lock(whenCondition: State.dataReady.rawValue)
defer { lock.unlock(withCondition: State.processing.rawValue) }
// 处理数据
data = data?.uppercased()
print("数据处理中: \(data ?? "")")
}
/// 阶段3:完成
func complete() {
// 等待 processing 状态
lock.lock(whenCondition: State.processing.rawValue)
defer { lock.unlock(withCondition: State.completed.rawValue) }
print("处理完成: \(data ?? "")")
}
/// 获取结果
func getResult() -> String? {
// 等待 completed 状态
lock.lock(whenCondition: State.completed.rawValue)
defer { lock.unlock(withCondition: State.idle.rawValue) } // 重置状态
return data
}
// MARK: - 带超时的操作
func processDataWithTimeout(timeout: TimeInterval) -> Bool {
let deadline = Date().addingTimeInterval(timeout)
if lock.lock(whenCondition: State.dataReady.rawValue, before: deadline) {
defer { lock.unlock(withCondition: State.processing.rawValue) }
data = data?.uppercased()
return true
} else {
print("等待超时")
return false
}
}
}
// MARK: - 实际应用:任务流水线
final class Pipeline<Input, Output> {
enum Stage: Int {
case idle = 0
case hasInput = 1
case hasOutput = 2
}
private let lock = NSConditionLock(condition: Stage.idle.rawValue)
private var input: Input?
private var output: Output?
private let transform: (Input) -> Output
init(transform: @escaping (Input) -> Output) {
self.transform = transform
}
/// 提交输入
func submit(_ value: Input) {
lock.lock(whenCondition: Stage.idle.rawValue)
input = value
lock.unlock(withCondition: Stage.hasInput.rawValue)
}
/// 处理(在工作线程调用)
func process() {
lock.lock(whenCondition: Stage.hasInput.rawValue)
if let input = input {
output = transform(input)
self.input = nil
}
lock.unlock(withCondition: Stage.hasOutput.rawValue)
}
/// 获取输出
func getOutput() -> Output {
lock.lock(whenCondition: Stage.hasOutput.rawValue)
let result = output!
output = nil
lock.unlock(withCondition: Stage.idle.rawValue)
return result
}
}
原子操作与无锁编程
原子操作原理
═══════════════════════════════════════════════════════════════════════════
原子操作原理
═══════════════════════════════════════════════════════════════════════════
原子操作:不可分割的操作,要么完成,要么不执行,没有中间状态。
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 非原子操作 count++: 原子操作 atomic_fetch_add: │
│ │
│ LOAD count → reg LOCK XADD count, 1 │
│ ADD reg, 1 ← 可被中断 → ↑ 单条指令,不可中断 │
│ STORE reg → count │
│ │
└─────────────────────────────────────────────────────────────────────────┘
CPU 原子操作实现方式:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 1. 总线锁定(Bus Lock)- 老方式 │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ CPU 锁定总线,其他 CPU 无法访问内存 │ │
│ │ 缺点:开销大,影响其他 CPU │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ 2. 缓存锁定(Cache Lock)- 现代方式 │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ 利用 MESI 缓存一致性协议 │ │
│ │ 只锁定缓存行,不锁定总线 │ │
│ │ 性能更好 │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ 3. CAS(Compare-And-Swap) │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ 比较并交换: │ │
│ │ if (memory == expected) { │ │
│ │ memory = newValue; │ │
│ │ return true; │ │
│ │ } else { │ │
│ │ return false; // 期望值不匹配 │ │
│ │ } │ │
│ │ ↑ 整个操作是原子的 │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
内存屏障(Memory Barrier):
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 问题:CPU 和编译器可能会重排序指令 │
│ │
│ ┌─────────────────┐ 重排序 ┌─────────────────┐ │
│ │ a = 1 │ ────→ │ b = 2 │ │
│ │ b = 2 │ │ a = 1 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 内存屏障类型: │
│ • LoadLoad - 确保屏障前的读操作先于屏障后的读操作 │
│ • StoreStore - 确保屏障前的写操作先于屏障后的写操作 │
│ • LoadStore - 确保屏障前的读操作先于屏障后的写操作 │
│ • StoreLoad - 确保屏障前的写操作先于屏障后的读操作 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
Swift Atomics
swift
// MARK: - Swift Atomics 库使用
import Atomics // Swift Atomics 包
/*
═══════════════════════════════════════════════════════════════════════════
Swift Atomics 使用指南
═══════════════════════════════════════════════════════════════════════════
添加依赖:
.package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.0")
*/
// MARK: - 原子整数
class AtomicIntDemo {
let counter = ManagedAtomic<Int>(0)
func increment() {
// 原子加法,返回旧值
let oldValue = counter.wrappingIncrement(ordering: .relaxed)
print("旧值: \(oldValue)")
}
func decrement() {
counter.wrappingDecrement(ordering: .relaxed)
}
func add(_ value: Int) {
counter.wrappingAdd(value, ordering: .relaxed)
}
func load() -> Int {
return counter.load(ordering: .relaxed)
}
func store(_ value: Int) {
counter.store(value, ordering: .relaxed)
}
// CAS 操作
func compareAndExchange(expected: Int, desired: Int) -> Bool {
let (exchanged, _) = counter.compareExchange(
expected: expected,
desired: desired,
ordering: .relaxed
)
return exchanged
}
}
// MARK: - 原子布尔值
class AtomicBoolDemo {
let flag = ManagedAtomic<Bool>(false)
/// 只执行一次的操作
func doOnce(_ action: () -> Void) {
// 尝试将 false 改为 true
let (exchanged, _) = flag.compareExchange(
expected: false,
desired: true,
ordering: .acquiringAndReleasing
)
if exchanged {
action() // 只有第一个成功的线程会执行
}
}
/// 获取并设置
func getAndSet(_ newValue: Bool) -> Bool {
return flag.exchange(newValue, ordering: .relaxed)
}
}
// MARK: - 原子引用
class AtomicReferenceDemo {
class Node {
let value: Int
var next: Node?
init(value: Int) {
self.value = value
}
}
let head = ManagedAtomic<Node?>(nil)
/// 无锁链表头插入
func pushFront(_ value: Int) {
let newNode = Node(value: value)
var done = false
while !done {
let currentHead = head.load(ordering: .relaxed)
newNode.next = currentHead
let (exchanged, _) = head.compareExchange(
expected: currentHead,
desired: newNode,
ordering: .acquiringAndReleasing
)
done = exchanged
}
}
/// 无锁弹出
func popFront() -> Int? {
while true {
guard let currentHead = head.load(ordering: .acquiring) else {
return nil // 空链表
}
let (exchanged, _) = head.compareExchange(
expected: currentHead,
desired: currentHead.next,
ordering: .acquiringAndReleasing
)
if exchanged {
return currentHead.value
}
// CAS 失败,重试
}
}
}
// MARK: - 内存顺序
/*
┌─────────────────────────────────────────────────────────────────────────┐
│ 内存顺序(Memory Ordering) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ .relaxed │
│ • 最弱的顺序保证 │
│ • 只保证操作的原子性 │
│ • 不保证与其他操作的顺序 │
│ • 性能最好 │
│ │
│ .acquiring │
│ • 读操作 │
│ • 保证此操作之后的读写不会被重排到此操作之前 │
│ │
│ .releasing │
│ • 写操作 │
│ • 保证此操作之前的读写不会被重排到此操作之后 │
│ │
│ .acquiringAndReleasing │
│ • 同时具有 acquiring 和 releasing 语义 │
│ • 用于 read-modify-write 操作 │
│ │
│ .sequentiallyConsistent │
│ • 最强的顺序保证 │
│ • 全局一致的顺序 │
│ • 性能最低 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
*/
OSAtomic(旧API)与 stdatomic
swift
// MARK: - OSAtomic(已废弃,了解即可)
import Darwin
/*
⚠️ OSAtomic 系列函数已被废弃,仅用于维护旧代码
推荐使用 Swift Atomics 或 os_unfair_lock
*/
class OSAtomicDemo {
var value: Int32 = 0
func atomicIncrement() {
// 原子自增
OSAtomicIncrement32(&value)
}
func atomicDecrement() {
// 原子自减
OSAtomicDecrement32(&value)
}
func atomicAdd(_ amount: Int32) {
// 原子加法
OSAtomicAdd32(amount, &value)
}
func atomicCompareAndSwap(expected: Int32, new: Int32) -> Bool {
// 原子 CAS
return OSAtomicCompareAndSwap32(expected, new, &value)
}
}
// MARK: - 使用 stdatomic(C11 原子操作)
/*
在 Swift 中使用 C11 原子操作需要通过桥接头文件
// Bridging-Header.h
#include <stdatomic.h>
// 定义原子类型
typedef struct {
_Atomic(int) value;
} AtomicInt;
static inline int atomic_load_int(AtomicInt* a) {
return atomic_load(&a->value);
}
static inline void atomic_store_int(AtomicInt* a, int v) {
atomic_store(&a->value, v);
}
static inline int atomic_fetch_add_int(AtomicInt* a, int v) {
return atomic_fetch_add(&a->value, v);
}
*/
无锁数据结构示例
swift
// MARK: - 无锁栈实现
final class LockFreeStack<T> {
private class Node {
let value: T
var next: UnsafeMutablePointer<Node>?
init(value: T) {
self.value = value
}
}
private var head = ManagedAtomic<UnsafeMutablePointer<Node>?>(nil)
func push(_ value: T) {
let newNode = UnsafeMutablePointer<Node>.allocate(capacity: 1)
newNode.initialize(to: Node(value: value))
var done = false
while !done {
let currentHead = head.load(ordering: .acquiring)
newNode.pointee.next = currentHead
let (exchanged, _) = head.compareExchange(
expected: currentHead,
desired: newNode,
ordering: .releasing
)
done = exchanged
}
}
func pop() -> T? {
while true {
guard let currentHead = head.load(ordering: .acquiring) else {
return nil
}
let nextNode = currentHead.pointee.next
let (exchanged, _) = head.compareExchange(
expected: currentHead,
desired: nextNode,
ordering: .acquiringAndReleasing
)
if exchanged {
let value = currentHead.pointee.value
currentHead.deinitialize(count: 1)
currentHead.deallocate()
return value
}
}
}
deinit {
while pop() != nil {}
}
}
// MARK: - 简单的原子计数器
final class AtomicCounter {
private let value = ManagedAtomic<Int>(0)
var current: Int {
value.load(ordering: .relaxed)
}
@discardableResult
func increment() -> Int {
value.wrappingAdd(1, ordering: .relaxed).newValue
}
@discardableResult
func decrement() -> Int {
value.wrappingSubtract(1, ordering: .relaxed).newValue
}
@discardableResult
func add(_ delta: Int) -> Int {
value.wrappingAdd(delta, ordering: .relaxed).newValue
}
func reset() {
value.store(0, ordering: .relaxed)
}
}
// MARK: - Once(只执行一次)
final class Once {
private let state = ManagedAtomic<Int>(0)
private enum State: Int {
case initial = 0
case running = 1
case completed = 2
}
func execute(_ action: () -> Void) {
// 快速路径:已完成
if state.load(ordering: .acquiring) == State.completed.rawValue {
return
}
// 尝试获取执行权
let (exchanged, _) = state.compareExchange(
expected: State.initial.rawValue,
desired: State.running.rawValue,
ordering: .acquiringAndReleasing
)
if exchanged {
// 执行
action()
// 标记完成
state.store(State.completed.rawValue, ordering: .releasing)
} else {
// 其他线程正在执行,等待完成
while state.load(ordering: .acquiring) != State.completed.rawValue {
// 自旋等待
}
}
}
}
锁的性能对比与选型
性能测试对比
swift
// MARK: - 锁性能测试
import Foundation
class LockBenchmark {
static let iterations = 1_000_000
// MARK: - 各种锁的性能测试
/// os_unfair_lock 测试
static func benchmarkUnfairLock() -> TimeInterval {
var lock = os_unfair_lock()
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
os_unfair_lock_lock(&lock)
counter += 1
os_unfair_lock_unlock(&lock)
}
return CFAbsoluteTimeGetCurrent() - start
}
/// pthread_mutex 测试
static func benchmarkPthreadMutex() -> TimeInterval {
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
defer { pthread_mutex_destroy(&mutex) }
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
pthread_mutex_lock(&mutex)
counter += 1
pthread_mutex_unlock(&mutex)
}
return CFAbsoluteTimeGetCurrent() - start
}
/// NSLock 测试
static func benchmarkNSLock() -> TimeInterval {
let lock = NSLock()
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
lock.lock()
counter += 1
lock.unlock()
}
return CFAbsoluteTimeGetCurrent() - start
}
/// DispatchSemaphore 测试
static func benchmarkDispatchSemaphore() -> TimeInterval {
let semaphore = DispatchSemaphore(value: 1)
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
semaphore.wait()
counter += 1
semaphore.signal()
}
return CFAbsoluteTimeGetCurrent() - start
}
/// @synchronized 测试
static func benchmarkSynchronized() -> TimeInterval {
let lockObj = NSObject()
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
objc_sync_enter(lockObj)
counter += 1
objc_sync_exit(lockObj)
}
return CFAbsoluteTimeGetCurrent() - start
}
/// NSRecursiveLock 测试
static func benchmarkRecursiveLock() -> TimeInterval {
let lock = NSRecursiveLock()
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
lock.lock()
counter += 1
lock.unlock()
}
return CFAbsoluteTimeGetCurrent() - start
}
/// DispatchQueue 测试
static func benchmarkDispatchQueue() -> TimeInterval {
let queue = DispatchQueue(label: "benchmark")
var counter = 0
let start = CFAbsoluteTimeGetCurrent()
for _ in 0..<iterations {
queue.sync {
counter += 1
}
}
return CFAbsoluteTimeGetCurrent() - start
}
// MARK: - 运行所有测试
static func runAll() {
print("锁性能测试(\(iterations) 次操作):")
print("─────────────────────────────────────")
let results: [(String, TimeInterval)] = [
("os_unfair_lock", benchmarkUnfairLock()),
("pthread_mutex", benchmarkPthreadMutex()),
("NSLock", benchmarkNSLock()),
("DispatchSemaphore", benchmarkDispatchSemaphore()),
("@synchronized", benchmarkSynchronized()),
("NSRecursiveLock", benchmarkRecursiveLock()),
("DispatchQueue", benchmarkDispatchQueue()),
]
// 按性能排序
let sorted = results.sorted { $0.1 < $1.1 }
for (index, (name, time)) in sorted.enumerated() {
let ms = time * 1000
print("\(index + 1). \(name): \(String(format: "%.2f", ms)) ms")
}
}
}
// 运行测试
// LockBenchmark.runAll()
性能对比结果分析
═══════════════════════════════════════════════════════════════════════════
锁性能对比(典型结果)
═══════════════════════════════════════════════════════════════════════════
测试环境:iPhone 14 Pro, iOS 17, 1,000,000 次加锁/解锁
┌─────────────────────────────────────────────────────────────────────────┐
│ 排名 │ 锁类型 │ 耗时(ms) │ 相对性能 │ 备注 │
├─────────────────────────────────────────────────────────────────────────┤
│ 1 │ os_unfair_lock │ ~25 │ 1.0x │ 最快 │
├─────────────────────────────────────────────────────────────────────────┤
│ 2 │ pthread_mutex │ ~30 │ 1.2x │ 接近最快 │
├─────────────────────────────────────────────────────────────────────────┤
│ 3 │ DispatchSemaphore │ ~35 │ 1.4x │ 推荐 │
├─────────────────────────────────────────────────────────────────────────┤
│ 4 │ NSLock │ ~50 │ 2.0x │ OC封装 │
├─────────────────────────────────────────────────────────────────────────┤
│ 5 │ DispatchQueue │ ~60 │ 2.4x │ 灵活性高 │
├─────────────────────────────────────────────────────────────────────────┤
│ 6 │ NSRecursiveLock │ ~70 │ 2.8x │ 递归支持 │
├─────────────────────────────────────────────────────────────────────────┤
│ 7 │ @synchronized │ ~100 │ 4.0x │ 最慢 │
└─────────────────────────────────────────────────────────────────────────┘
选型建议:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 📊 性能优先: │
│ os_unfair_lock > pthread_mutex > DispatchSemaphore │
│ │
│ 🔧 功能优先: │
│ • 需要超时 → NSLock (lock(before:)) │
│ • 需要递归 → NSRecursiveLock │
│ • 需要条件 → NSCondition / pthread_cond │
│ • 读写分离 → pthread_rwlock / GCD barrier │
│ │
│ 📦 便捷性优先: │
│ • Swift → DispatchQueue / DispatchSemaphore │
│ • OC → @synchronized(简单场景) │
│ │
│ ⚡ 高并发场景: │
│ • 读多写少 → 读写锁 / GCD concurrent + barrier │
│ • 无锁编程 → Swift Atomics(复杂,谨慎使用) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
锁的选型决策树
═══════════════════════════════════════════════════════════════════════════
锁选型决策树
═══════════════════════════════════════════════════════════════════════════
需要线程同步?
│
▼
┌─────────────────────┐
│ 是否只需要简单的互斥?│
└──────────┬──────────┘
│
┌──────────────┴──────────────┐
│ │
▼ 是 ▼ 否
┌─────────────────┐ ┌─────────────────────┐
│ 临界区是否极短? │ │ 需要什么额外功能? │
└────────┬────────┘ └──────────┬──────────┘
│ │
┌───────┴───────┐ ┌──────────┼──────────┐
│ │ │ │ │
▼ 是 ▼ 否 ▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│os_unfair│ │ NSLock │ │ 递归 │ │ 条件 │ │读写分离│
│ _lock │ │ 或 │ │ │ │ │ │ │
│ │ │pthread_ │ │ │ │ │ │ │
│ │ │ mutex │ │ │ │ │ │ │
└─────────┘ └──────────┘ └───┬────┘ └───┬────┘ └───┬────┘
│ │ │
▼ ▼ ▼
NSRecursive NSCondition pthread_
Lock NSCondition rwlock
Lock 或
GCD barrier
特殊场景选择:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 场景 │ 推荐方案 │
│ ────────────────────────────────────────────────────────────────────│
│ 高频简单读写 │ os_unfair_lock │
│ 需要超时控制 │ NSLock + lock(before:) │
│ 递归调用场景 │ NSRecursiveLock │
│ 生产者-消费者 │ NSCondition / DispatchSemaphore │
│ 状态机 │ NSConditionLock │
│ 读多写少 │ pthread_rwlock / GCD barrier │
│ 需要最大灵活性 │ GCD DispatchQueue │
│ OC遗留代码 │ @synchronized │
│ 极致性能 │ 原子操作(无锁) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
═══════════════════════════════════════════════════════════════════════════
实战应用场景
场景1:线程安全的单例
swift
// MARK: - 单例的各种实现方式
// 方式1:dispatch_once(推荐)
class Singleton1 {
static let shared = Singleton1()
private init() {}
}
// 方式2:原子标志
class Singleton2 {
private static var instance: Singleton2?
private static let once = Once()
static var shared: Singleton2 {
once.execute {
instance = Singleton2()
}
return instance!
}
private init() {}
}
// 方式3:双重检查锁定(DCL)
class Singleton3 {
private static var instance: Singleton3?
private static let lock = NSLock()
static var shared: Singleton3 {
if instance == nil {
lock.lock()
defer { lock.unlock() }
if instance == nil {
instance = Singleton3()
}
}
return instance!
}
private init() {}
}
场景2:线程安全的懒加载
swift
// MARK: - 线程安全的懒加载
class LazyLoader<T> {
private var _value: T?
private let lock = UnfairLock()
private let initializer: () -> T
init(_ initializer: @escaping () -> T) {
self.initializer = initializer
}
var value: T {
lock.lock()
defer { lock.unlock() }
if let existing = _value {
return existing
}
let newValue = initializer()
_value = newValue
return newValue
}
var isInitialized: Bool {
lock.withLock { _value != nil }
}
func reset() {
lock.withLock {
_value = nil
}
}
}
// 使用示例
class ImageCache {
private let expensiveResource = LazyLoader {
// 耗时的初始化
print("初始化资源...")
Thread.sleep(forTimeInterval: 1)
return ["data": "expensive"]
}
func getResource() -> [String: String] {
return expensiveResource.value
}
}
场景3:线程安全的字典
swift
// MARK: - 完整的线程安全字典
final class ThreadSafeDictionary<Key: Hashable, Value> {
private var dictionary: [Key: Value]
private let lock: ReadWriteLock
init(_ dictionary: [Key: Value] = [:]) {
self.dictionary = dictionary
self.lock = ReadWriteLock()
}
// MARK: - 读操作
subscript(key: Key) -> Value? {
get {
lock.withReadLock { dictionary[key] }
}
set {
lock.withWriteLock { dictionary[key] = newValue }
}
}
var count: Int {
lock.withReadLock { dictionary.count }
}
var isEmpty: Bool {
lock.withReadLock { dictionary.isEmpty }
}
var keys: [Key] {
lock.withReadLock { Array(dictionary.keys) }
}
var values: [Value] {
lock.withReadLock { Array(dictionary.values) }
}
func contains(_ key: Key) -> Bool {
lock.withReadLock { dictionary[key] != nil }
}
// MARK: - 写操作
@discardableResult
func removeValue(forKey key: Key) -> Value? {
lock.withWriteLock { dictionary.removeValue(forKey: key) }
}
func removeAll() {
lock.withWriteLock { dictionary.removeAll() }
}
@discardableResult
func updateValue(_ value: Value, forKey key: Key) -> Value? {
lock.withWriteLock { dictionary.updateValue(value, forKey: key) }
}
// MARK: - 复合操作
/// 如果不存在则设置
@discardableResult
func setIfAbsent(_ key: Key, value: Value) -> Value {
lock.withWriteLock {
if let existing = dictionary[key] {
return existing
}
dictionary[key] = value
return value
}
}
/// 获取或创建
func getOrCreate(_ key: Key, creator: () -> Value) -> Value {
// 先尝试读取
if let existing = lock.withReadLock({ dictionary[key] }) {
return existing
}
// 不存在则加写锁创建
return lock.withWriteLock {
// 双重检查
if let existing = dictionary[key] {
return existing
}
let newValue = creator()
dictionary[key] = newValue
return newValue
}
}
/// 批量更新
func merge(_ other: [Key: Value]) {
lock.withWriteLock {
dictionary.merge(other) { _, new in new }
}
}
/// 条件更新
func updateIf(_ key: Key, condition: (Value) -> Bool, transform: (Value) -> Value) -> Bool {
lock.withWriteLock {
guard let current = dictionary[key], condition(current) else {
return false
}
dictionary[key] = transform(current)
return true
}
}
}
场景4:任务调度器
swift
// MARK: - 线程安全的任务调度器
final class TaskScheduler {
private var tasks: [ScheduledTask] = []
private let lock = NSCondition()
private var isRunning = false
private var workerThread: Thread?
struct ScheduledTask {
let id: String
let executeTime: Date
let action: () -> Void
}
/// 调度任务
func schedule(after delay: TimeInterval, action: @escaping () -> Void) -> String {
let taskId = UUID().uuidString
let executeTime = Date().addingTimeInterval(delay)
lock.lock()
defer { lock.unlock() }
let task = ScheduledTask(id: taskId, executeTime: executeTime, action: action)
// 按执行时间排序插入
if let insertIndex = tasks.firstIndex(where: { $0.executeTime > executeTime }) {
tasks.insert(task, at: insertIndex)
} else {
tasks.append(task)
}
// 唤醒工作线程
lock.signal()
return taskId
}
/// 取消任务
func cancel(_ taskId: String) -> Bool {
lock.lock()
defer { lock.unlock() }
if let index = tasks.firstIndex(where: { $0.id == taskId }) {
tasks.remove(at: index)
return true
}
return false
}
/// 启动调度器
func start() {
lock.lock()
defer { lock.unlock() }
guard !isRunning else { return }
isRunning = true
workerThread = Thread { [weak self] in
self?.runLoop()
}
workerThread?.start()
}
/// 停止调度器
func stop() {
lock.lock()
isRunning = false
lock.signal() // 唤醒可能在等待的线程
lock.unlock()
workerThread = nil
}
private func runLoop() {
lock.lock()
defer { lock.unlock() }
while isRunning {
if tasks.isEmpty {
// 没有任务,等待
lock.wait()
continue
}
let now = Date()
let nextTask = tasks.first!
if nextTask.executeTime <= now {
// 执行任务
tasks.removeFirst()
// 解锁后执行,避免长时间持有锁
lock.unlock()
nextTask.action()
lock.lock()
} else {
// 等待到执行时间
lock.wait(until: nextTask.executeTime)
}
}
}
}
场景5:对象池
swift
// MARK: - 线程安全的对象池
final class ObjectPool<T> {
private var available: [T] = []
private var inUse: Set<ObjectWrapper<T>> = []
private let lock = NSCondition()
private let maxSize: Int
private let factory: () -> T
init(maxSize: Int, factory: @escaping () -> T) {
self.maxSize = maxSize
self.factory = factory
}
/// 获取对象
func acquire() -> T {
lock.lock()
defer { lock.unlock() }
// 等待有可用对象
while available.isEmpty && inUse.count >= maxSize {
lock.wait()
}
let object: T
if let pooledObject = available.popLast() {
object = pooledObject
} else {
object = factory()
}
inUse.insert(ObjectWrapper(object))
return object
}
/// 获取对象(带超时)
func acquire(timeout: TimeInterval) -> T? {
lock.lock()
defer { lock.unlock() }
let deadline = Date().addingTimeInterval(timeout)
while available.isEmpty && inUse.count >= maxSize {
if !lock.wait(until: deadline) {
return nil // 超时
}
}
let object: T
if let pooledObject = available.popLast() {
object = pooledObject
} else {
object = factory()
}
inUse.insert(ObjectWrapper(object))
return object
}
/// 归还对象
func release(_ object: T) {
lock.lock()
defer { lock.unlock() }
let wrapper = ObjectWrapper(object)
guard inUse.remove(wrapper) != nil else {
return // 不是从池中获取的对象
}
available.append(object)
lock.signal() // 通知等待的线程
}
/// 当前可用数量
var availableCount: Int {
lock.lock()
defer { lock.unlock() }
return available.count
}
/// 当前使用中数量
var inUseCount: Int {
lock.lock()
defer { lock.unlock() }
return inUse.count
}
// 对象包装器(用于 Set)
private class ObjectWrapper<O>: Hashable {
let object: O
init(_ object: O) {
self.object = object
}
static func == (lhs: ObjectWrapper<O>, rhs: ObjectWrapper<O>) -> Bool {
return lhs === rhs
}
func hash(into hasher: inout Hasher) {
hasher.combine(ObjectIdentifier(self))
}
}
}
// 使用示例
class DatabaseConnection {
let id = UUID()
func query(_ sql: String) -> [String] {
// 执行查询
return []
}
}
let connectionPool = ObjectPool<DatabaseConnection>(maxSize: 10) {
DatabaseConnection()
}
// 使用连接
let connection = connectionPool.acquire()
let results = connection.query("SELECT * FROM users")
connectionPool.release(connection)
总结
┌─────────────────────────────────────────────────────────────────────────────┐
│ iOS 锁的本质 - 核心要点 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 🔒 锁的本质 │
│ • 确保临界区代码的互斥执行 │
│ • 解决多线程数据竞争问题 │
│ • 本质是原子操作 + 等待/唤醒机制 │
│ │
│ ⚡ 自旋锁(os_unfair_lock) │
│ • 忙等待,不让出 CPU │
│ • 适合临界区极短的场景 │
│ • 性能最好,但要注意优先级反转 │
│ │
│ 🔐 互斥锁(pthread_mutex / NSLock) │
│ • 休眠等待,让出 CPU │
│ • 适合大多数场景 │
│ • 有上下文切换开销 │
│ │
│ 🔄 递归锁(NSRecursiveLock) │
│ • 同一线程可重复加锁 │
│ • 维护重入计数 │
│ • 性能较普通锁低,尽量避免使用 │
│ │
│ 📖 读写锁(pthread_rwlock / GCD barrier) │
│ • 读-读 可并发 │
│ • 读-写、写-写 互斥 │
│ • 适合读多写少场景 │
│ │
│ ⏳ 条件锁(NSCondition / NSConditionLock) │
│ • 等待特定条件成立 │
│ • 适合生产者-消费者模式 │
│ • wait() 原子地释放锁并休眠 │
│ │
│ ⚛️ 原子操作 │
│ • 无锁编程基础 │
│ • CAS(Compare-And-Swap) │
│ • 适合简单计数器、标志位 │
│ │
│ 📊 性能排序(由快到慢) │
│ os_unfair_lock > pthread_mutex > DispatchSemaphore > │
│ NSLock > DispatchQueue > NSRecursiveLock > @synchronized │
│ │
│ ✅ 最佳实践 │
│ • 临界区尽量短 │
│ • 避免锁嵌套(防死锁) │
│ • 使用 defer 确保解锁 │
│ • 选择合适的锁类型 │
│ • 考虑使用 GCD 替代显式锁 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
理解锁的本质对于编写高性能、线程安全的代码至关重要。选择合适的锁类型,正确使用锁的API,避免常见的陷阱(如死锁、优先级反转),是每个 iOS 开发者必须掌握的技能。