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
  • 复杂场景应考虑其他锁机制
相关推荐
_瑞16 小时前
AI Coding 那么快,为什么还需要 SDD?
人工智能·ios·ai编程
轩辕十四leo17 小时前
Astrolabe(星盘):让 AI 看见自己写出的 UI
ios·ai编程
白玉cfc18 小时前
熟悉Objective-C
开发语言·ios·objective-c
星辰即远方1 天前
字符串合法性检验
macos·ios·cocoa
末代iOS程序员华仔1 天前
KMP全栈开发:从Android到AI Agent的技术演进与实践
flutter·ios·figma
2501_916008891 天前
苹果上架工具怎么选 不用 Mac 上架 App Store 的几种方案
android·macos·ios·小程序·uni-app·iphone·webview
鹤卿1232 天前
谓词与正则表达式(OC)
ios·正则表达式·objective-c·xcode
秋雨梧桐叶落莳2 天前
iOS——3GShare项目总结
学习·macos·ios·objective-c·cocoa
AIsoft_86882 天前
iOS端录音转文字工具实测:自媒体创作者高效整理指南
ios·媒体
库奇噜啦呼3 天前
【iOS】Core Data
ios