美文网首页
不再安全的 OSSpinLock

不再安全的 OSSpinLock

作者: 大白龙 | 来源:发表于2019-08-06 16:32 被阅读0次

YY大神原文链接:不再安全的 OSSpinLock

OSSpinLock 的问题

2015-12-14 那天, swift-dev 邮件列表里 有人在讨论 weak 属性的线程安全问题,其中有几位苹果工程师透露了自旋锁的问题,对话内容大致如下:

新版 iOS 中,系统维护了 5 个不同的线程优先级 /QoS: background , utility , default , user-initiated , user-interactive 。高优先级线程始终会在低优先级线程前执行,一个线程不会受到比它更低优先级线程的干扰。这种线程调度算法会产生潜在的优先级反转问题,从而破坏了 spin lock 。

具体来说,如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU 。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock 。这并不只是理论上的问题, libobjc 已经遇到了很多次这个问题了,于是苹果的工程师停用了 OSSpinLock 。

苹果工程师 Greg Parker 提到,对于这个问题,一种解决方案是用 truly unbounded backoff 算法,这能避免 livelock 问题,但如果系统负载高时,它仍有可能将高优先级的线程阻塞数十秒之久;另一种方案是使用 handoff lock 算法,这也是 libobjc 目前正在使用的。锁的持有者会把线程 ID 保存到锁内部,锁的等待者会临时贡献出它的优先级来避免优先级反转的问题。理论上这种模式会在比较复杂的多锁条件下产生问题,但实践上目前还没有遇到问题。

libobjc 里用的是 Mach 内核的 thread_switch() 然后传递了一个 mach thread port 来避免优先级反转,另外它还用了一个私有的参数选项,所以开发者无法自己实现这个锁。另一方面,由于二进制兼容问题, OSSpinLock 也不能有改动。

最终的结论就是,除非开发者能保证访问锁的线程全部都处于同一优先级,否则 iOS 系统中所有类型的自旋锁都不能再使用了。

OSSpinLock 的替代方案

为了找到一个替代方案,我做了一个简单的性能测试,对比了一下几种能够替代 OSSpinLock 锁的性能。测试是在 iPhone6 、 iOS9 上跑的,代码在 这里 。我尝试了不同的循环次数,结果并不都一样,我猜这可能是与 CPU Cache 有关,所以这个结果只能当作一个定性分析。

iOS锁的性能

可以看到除了 OSSpinLock 外, dispatch_semaphore 和 pthread_mutex 性能是最高的。有 消息 称,苹果在新系统中已经优化了 pthread_mutex 的性能,所以它看上去和 OSSpinLock 差距并没有那么大了。

开源社区的反应

苹果

查看 CoreFoundation 的源码能够发现,苹果至少在 2014 年就发现了这个问题,并把 CoreFoundation 中的 spinlock 替换成了 pthread_mutex ,具体变化可以查看这两个文件: CFInternal.h(855.17) 、 CFInternal.h(1151.16) 。 苹果自己发现问题后,并没有更新 OSSpinLock 的文档,也没有告知开发者,这有些让人失望。

Google

google/ protobuf 内部的 spinlock 被全部 替换为 dispatch_semaphore ,详情可以看这个提交: https://github.com/google/protobuf/pull/1060 。用 dispatch_semaphore 而不用 pthread_mutex 应该是出于性能考虑。

其他项目

因为 OSSpinLock 出现这种问题的几率很小,也没有引起很大的重视,我所能找到的也只有 ReactiveCocoa 在讨论这个问题。

相关文章

  • 不再安全的 OSSpinLock

    YY大神原文链接:不再安全的 OSSpinLock OSSpinLock 的问题 2015-12-14 那天, s...

  • oc中的8种锁

    这两天翻看 ibireme 大神 《不再安全的 OSSpinLock[http://blog.ibireme.co...

  • 线程锁

    OSSpinLock OSSpinLock 不再安全,主要原因发生在低优先级线程拿到锁时,高优先级线程进入忙等(b...

  • iOS 不安全的OSSpinLock锁

    iOS 不安全的OSSpinLock锁 OSSpinLock OSSpinLock 是自旋锁,等待锁的线程会处于忙...

  • 【iOS】 常见的各种锁Lock 🔐

    1. 性能对比 (来自 ibireme 的 [不再安全的 OSSpinLock][] 一文) 2. 特点分析 2....

  • iOS锁-OSSpinLock与os_unfair_lock

    OSSpinLock与os_unfair_lock OSSpinLock 已经被Apple废弃,因为线程安全问题,...

  • iOS 开发中的八种锁(Lock)

    这两天翻看 ibireme 大神 《不再安全的 OSSpinLock》 这篇文章,看到文中分析各种锁之前的性能的图...

  • iOS中常见的10种锁

    首先看一下它们的性能对比: 下面开始逐个分析 1. OSSpinLock 自旋锁 参考YY大神的不再安全的自旋锁 ...

  • iOS 笔记 - 锁

    今天简单写一下iOS中相关锁的内容,下图来自不再安全的 OSSpinLock中几种常见的锁加解锁的时间。 废弃的O...

  • OSSpinLock

    自旋锁,和互斥锁类似,都是为了保证线程安全的锁。但二者的区别是不一样的,对于互斥锁,当一个线程获得这个锁之后,其他...

网友评论

      本文标题:不再安全的 OSSpinLock

      本文链接:https://www.haomeiwen.com/subject/ptjwdctx.html