iOS - 自旋锁

在 Objective-C 运行时中大量使用自旋锁,主要有以下几个原因:

1. 性能考虑

上下文切换成本

objectivec 复制代码
// 自旋锁实现
static ALWAYS_INLINE void OSSpinLockLock(volatile OSSpinLock *lock) {
    do {
        while (lock->value != 0) {
            __asm__ volatile ("pause");  // 不释放CPU,继续尝试
        }
    } while (!OSAtomicCompareAndSwap32(0, 1, &lock->value));
}

// 相比互斥锁的实现
pthread_mutex_lock(&mutex);   // 可能导致线程休眠和上下文切换
// ... 
pthread_mutex_unlock(&mutex);

优势:

  1. 避免了线程上下文切换的开销
  2. 适合短期持有的场景
  3. 在多核处理器上效率更高

2. 使用场景特点

短暂的临界区

objectivec 复制代码
// 属性访问的典型场景
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (!atomic) return *((id *)((char *)self + offset));
    
    spinlock_t& slotlock = PropertyLocks[GOODHASH(offset)];
    slotlock.lock();    // 持锁时间极短
    id value = *((id *)((char *)self + offset));
    slotlock.unlock();
    return value;
}

特点:

  1. 锁的持有时间非常短
  2. 竞争不激烈
  3. 代码路径简单

3. 内存效率

结构简单

objectivec 复制代码
typedef struct {
    volatile int32_t value;  // 仅需要一个32位整数
} OSSpinLock;

// 相比互斥锁的复杂结构
struct pthread_mutex_t {
    // ... 更复杂的内部结构
    // 包含条件变量、等待队列等
};

优势:

  1. 内存占用小
  2. 缓存友好
  3. 初始化成本低

4. 适用的情况

理想场景

objectivec 复制代码
// 引用计数操作
inline bool objc_object::sidetable_tryRetain() {
    SideTable& table = SideTables()[this];
    bool result = false;
    
    table.lock();   // 快速的加锁解锁
    // 简单的引用计数操作
    table.unlock();
    
    return result;
}

最佳实践:

  1. 临界区执行时间短
  2. 线程等待时间短
  3. CPU资源充足

5. 潜在问题

优先级反转

objectivec 复制代码
// 可能出现的问题场景
while (lock->value != 0) {
    // 如果持有锁的是低优先级线程
    // 而等待的是高优先级线程
    // 可能导致优先级反转
    __asm__ volatile ("pause");
}

解决方案:

  1. iOS 10 后系统更多使用 os_unfair_lock
  2. 对于复杂场景使用互斥锁
  3. 需要考虑优先级时使用其他锁机制

6. 使用建议

适合使用自旋锁的场景

objectivec 复制代码
// 1. 简单的原子操作
atomic_property.lock();
value = _property;
atomic_property.unlock();

// 2. 快速的引用计数操作
spinlock.lock();
refCount++;
spinlock.unlock();

不适合使用自旋锁的场景

objectivec 复制代码
// 1. 复杂的操作
lock.lock();
[self complexOperation];  // 耗时操作
lock.unlock();

// 2. 可能阻塞的操作
lock.lock();
[self operationMayBlock];  // 可能阻塞
lock.unlock();

7. 总结

自旋锁在 Objective-C 运行时中的广泛使用是基于以下考虑:

  1. 性能优化:避免上下文切换
  2. 场景匹配:适合短期、快速的操作
  3. 资源效率:内存占用小,初始化快
  4. 实现简单:容易维护和调试
  5. 硬件友好:在现代多核处理器上表现良好

但需要注意:

  • 不适合长时间持有
  • 要考虑优先级反转问题
  • iOS 10 后推荐使用 os_unfair_lock
  • 复杂场景应考虑其他锁机制
相关推荐
2501_9159214316 分钟前
查看iOS App实时日志的正确方式,多工具协同打造高效调试与问题定位体系(2025最新指南)
android·ios·小程序·https·uni-app·iphone·webview
ajassi20003 小时前
开源 Objective-C IOS 应用开发(四)Xcode工程文件结构
ios·开源·objective-c
G佳伟4 小时前
如何解决解决,微信小程序ios无法长按复制问题<text>设置 selectable=“true“不起作用
ios·微信小程序·小程序
Nick56834 小时前
Apple Pay 与 Google Pay 开发与结算全流程文档
ios·安卓·android-studio
全栈派森4 小时前
初见 Dart:这门新语言如何让你的 App「动」起来?
android·flutter·ios
HarderCoder5 小时前
Swift 内存管理:吃透 ARC 、weak、unowned
ios·swift
Digitally5 小时前
5种将照片从iPhone传输到戴尔PC/笔记本电脑的方法
ios·电脑·iphone
ajassi20006 小时前
开源 Objective-C IOS 应用开发(三)第一个iPhone的APP
ios·开源·objective-c
Daniel_Coder11 小时前
iOS Widget 开发-9:可配置 Widget:使用 IntentConfiguration 实现参数选择
ios·swiftui·swift·widget·intents
非专业程序员Ping14 小时前
Vibe Coding 实战!花了两天时间,让 AI 写了一个富文本渲染引擎!
ios·ai·swift·claude·vibecoding