本文只是我对iOS中锁的学习笔记,没有太深入的研究讲解。先来一张ios中常用锁的性能对照图

锁的分类
自旋锁:在未获取到锁的情况下,线程会反复检查锁变量是否可用,处于一直忙等状态,所以不会进行上下文切换,适用于阻塞很短时间的场景,常见的锁有OSSpinLock,另外atomic修饰符内部也是使用的自旋锁。
互斥锁:是一种用于多线程编程中,防止两条线程同时对同一公共资源(比 如全局变量)进行读写的机制。它可以将代码切片成一个一个的临界区以达到锁的目的。拿不到锁的线程会进入睡眠状态,等待其他线程释放锁后将其唤醒。NSLock、pthread_mutex、@synchronized都属于互斥锁。
OSSpinLock(自旋锁)
由于多线程优先级反转问题,可能导致优先级高的线程一直处于忙等状态,而优化级低的线程又拿不到锁,所以ios10开始已被os_unfair_lock取代。
dispatch_semaphore
一种比较高级的线程间同步机制,互斥锁可以说是semaphore在仅取值0/1时的特例。
pthread_mutex、NSLock、NSRecursiveLock
NSLock和NSRecursiveLock都是基于pthread_mutex互斥锁实现,但NSRecursiveLock支持递归调用。
NSCondition、NSConditionLock
其底层是使用的互斥锁,但在此基础上增加了线程间通讯的能力,通过相应的api可以控制线程的执行流程。
synchronized分析
被@synchronized包裹的代码块会被编译器转换成objc_sync_enter和objc_sync_exit,并且在加解锁时是操作的SyncData这个对象
typedef struct alignas(CacheLineSize) SyncData {
struct SyncData* nextData;
DisguisedPtr<objc_object> object;
int32_t threadCount; // number of THREADS using this block
recursive_mutex_t mutex;
} SyncData;
SyncData存储在线程缓存中,是一个链表,主要用于针对不同对象加锁的情况。另外其中threadCount是用于多线程的场景,如果多个线程对同一个对象加锁,只会增加threadCount的值。如果是同一个线程对同一对象多次加锁,例如嵌套的情况,那么会操作线程缓存中的lockCount变量。
推荐学习:
iOS-底层原理 29:锁的原理
网友评论