直播系统源码,iOS中的自旋锁详解
直播系统源码,iOS中的自旋锁详解
自从OSSpinLock出现了安全问题之后就废弃了。自旋锁之所以不安全,是因为自旋锁由于获取锁时,线程会一直处于忙等待状态,造成了任务的优先级反转
而OSSpinLock忙等的机制就可能造成高优先级一直running等待,占用CPU时间片;而低优先级任务无法抢占时间片,变成迟迟完不成,不释放锁的情况
在iOS探索 KVC原理及自定义中有提到自动生成的setter方法会根据修饰符不同调用不同方法,最后统一调用reallySetProperty方法,其中就有一段关于atomic修饰词的代码
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy) { if (offset == 0) { object_setClass(self, newValue); return; } id oldValue; id *slot = (id*) ((char*)self + offset); if (copy) { newValue = [newValue copyWithZone:nil]; } else if (mutableCopy) { newValue = [newValue mutableCopyWithZone:nil]; } else { if (*slot == newValue) return; newValue = objc_retain(newValue); } if (!atomic) { oldValue = *slot; *slot = newValue; } else { spinlock_t& slotlock = PropertyLocks[slot]; slotlock.lock(); oldValue = *slot; *slot = newValue; slotlock.unlock(); } objc_release(oldValue); }
比对一下atomic的逻辑分支:
1、原子性修饰的属性进行了spinlock加锁处理
2、非原子性的属性除了没加锁,其他逻辑与atomic一般无二
等等,前面不是刚说OSSpinLock因为安全问题被废弃了吗,但是苹果源码怎么还在使用呢?其实点进去就会发现用os_unfair_lock替代了OSSpinLock(iOS10之后替换)
using spinlock_t = mutex_tt<LOCKDEBUG>; class mutex_tt : nocopy_t { os_unfair_lock mLock; ... }
同时为了哈希不冲突,还使用加盐操作进行加锁
getter方法亦是如此:atomic修饰的属性进行加锁处理
id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) { if (offset == 0) { return object_getClass(self); } // Retain release world id *slot = (id*) ((char*)self + offset); if (!atomic) return *slot; // Atomic retain release world spinlock_t& slotlock = PropertyLocks[slot]; slotlock.lock(); id value = objc_retain(*slot); slotlock.unlock(); // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock. return objc_autoreleaseReturnValue(value); }
读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的CPU数
写者是排他性的,⼀个读写锁同时只能有⼀个写者或多个读者(与CPU数相关),但不能同时既有读者⼜有写者。在读写锁保持期间也是抢占失效的
如果读写锁当前没有读者,也没有写者,那么写者可以⽴刻获得读写锁,否则它必须⾃旋在那⾥,直到没有任何写者或读者。如果读写锁没有写者,那么读者可以⽴即获得该读写锁,否则读者必须⾃旋在那⾥,直到写者释放该读写锁
// 导入头文件 #import <pthread.h> // 全局声明读写锁 pthread_rwlock_t lock; // 初始化读写锁 pthread_rwlock_init(&lock, NULL); // 读操作-加锁 pthread_rwlock_rdlock(&lock); // 读操作-尝试加锁 pthread_rwlock_tryrdlock(&lock); // 写操作-加锁 pthread_rwlock_wrlock(&lock); // 写操作-尝试加锁 pthread_rwlock_trywrlock(&lock); // 解锁 pthread_rwlock_unlock(&lock); // 释放锁 pthread_rwlock_destroy(&lock);
平时很少会直接使用读写锁pthread_rwlock_t,更多的是采用其他方式,例如使用栅栏函数完成读写锁的需求
以上就是直播系统源码,iOS中的自旋锁详解, 更多内容欢迎关注之后的文章