当线程等待自旋锁时不会进入睡眠,自旋锁由于在获取锁时,线程会一直处于忙等状态,有可能会造成任务的优先级反转。
新版 iOS 中,系统维护了 5 个不同的线程优先级/QoS: background,utility,default,user-initiated,user-interactive。高优先级线程始终会在低优先级线程前执行,一个线程不会受到比它更低优先级线程的干扰。这种线程调度算法会产生潜在的优先级反转问题,从而破坏了 spin lock。
具体来说,如果一个低优先级的线程获得锁并访问共享资源,这时一个高优先级的线程也尝试获得这个锁,它会处于 spin lock 的忙等状态从而占用大量 CPU。此时低优先级线程无法与高优先级线程争夺 CPU 时间,从而导致任务迟迟完不成、无法释放 lock。这并不只是理论上的问题,libobjc 已经遇到了很多次这个问题了,于是苹果的工程师停用了 OSSpinLock。
当等待互斥锁时,线程会进入睡眠,锁释放时就会唤醒线程。互斥锁又分为递归锁和非递归锁:
pthread_mutex
是互斥锁,对性能要求比较高的场景可以使用, API 比较简单:
// 导入头文件
#import <pthread.h>
// 全局声明互斥锁
pthread_mutex_t _lock;
// 初始化互斥锁
pthread_mutex_init(&_lock, NULL);
// 加锁
pthread_mutex_lock(&_lock);
// 这里做需要线程安全操作
// 解锁
pthread_mutex_unlock(&_lock);
// 释放锁
pthread_mutex_destroy(&_lock);
mikeash.com: Friday Q&A 2015-02-20: Let's Build @synchronized
性能比较低,因为有容错处理,和使用全局表。
非OC对象
作为加锁条件——id2data
中接收参数为id类型增删改查
消耗了大量性能