线程同步问题
文章目录
OSSpinLock
-
已不安全,不推荐使用
-
OSSpinLock叫做”自旋锁”,等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源
-
目前已经不再安全,可能会出现优先级反转问题
- 如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁(优先级比较低的线程一直拿不到CPU 就无法释放锁,优先级高的一直拿不到锁,就处于死锁状态)
- 需要导入头文件 #import <libkern/OSAtomic.h>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RTv3htlD-1586360075303)(media/15414898062564/15816946374692.jpg)]
os_unfair_lock
-
os_unfair_lock用于取代不安全的OSSpinLock ,从iOS10开始才支持
-
从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等
-
需要导入头文件#import <os/lock.h>
-
实际上也是互斥锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsW5RfmD-1586360075304)(media/15414898062564/15816950992558.jpg)]
pthread_mutex
pthread_mutex 互斥锁
-
mutex叫做”互斥锁”,等待锁的线程会处于休眠状态
-
需要导入头文件#import <pthread.h>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6VvTtNt-1586360075305)(media/15414898062564/15816980650497.jpg)]
pthread_mutex 递归锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZoeOXbG-1586360075307)(media/15414898062564/15817860472078.jpg)]
pthread_mutex 条件锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sl5w6GDc-1586360075308)(media/15414898062564/15817861101084.jpg)]
NSLock、NSRecursiveLock
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJsiEVFh-1586360075309)(media/15414898062564/15817861562700.jpg)]
NSCondition
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQJigzbv-1586360075312)(media/15414898062564/15817870358064.jpg)]
NSConditionLock
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGA3T6uF-1586360075313)(media/15414898062564/15817870542568.jpg)]
dispatch_semaphore
- semaphore叫做”信号量”
- 信号量的初始值,可以用来控制线程并发访问的最大数量
- 信号量的初始值为1,代表同时只允许1条线程访问资源,保证线程同步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ml3oQZSU-1586360075315)(media/15414898062564/15817871175345.jpg)]
dispatch_queue(DISPATCH_QUEUE_SERIAL)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Fve9wXl-1586360075316)(media/15414898062564/15817871453934.jpg)]
@synchronized
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DfwJYxg7-1586360075317)(media/15414898062564/15817871634320.jpg)]
线程同步方案性能比较
- 性能从高到低排序
- os_unfair_lock (不公平的 iOS10开始使用,10以前版本不支持)
- OSSpinLock (spin 旋转 不推荐使用)
- dispatch_semaphore (推荐使用)
- pthread_mutex (mutex 互斥) (推荐使用)
- dispatch_queue(DISPATCH_QUEUE_SERIAL)
- NSLock
- NSCondition
- pthread_mutex(recursive)
- NSRecursiveLock
- NSConditionLock
- @synchronized
自旋锁、互斥锁比较
-
什么情况使用自旋锁比较划算?
- 预计线程等待锁的时间很短
- 加锁的代码(临界区)经常被调用,但竞争情况很少发生
- CPU资源不紧张
- 多核处理器
-
什么情况使用互斥锁比较划算?
- 预计线程等待锁的时间较长
- 单核处理器
- 临界区有IO操作
- 临界区代码复杂或者循环量大
- 临界区竞争非常激烈
iOS中的读写安全方案
-
思考如何实现以下场景
- 同一时间,只能有1个线程进行写的操作
- 同一时间,允许有多个线程进行读的操作
- 同一时间,不允许既有写的操作,又有读的操作
-
上面的场景就是典型的“多读单写”,经常用于文件等数据的读写操作,iOS中的实现方案有
- pthread_rwlock:读写锁
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swpFVImT-1586360075318)(media/15414898062564/15818728584498.jpg)]
-
dispatch_barrier_async:异步栅栏调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9N6CRpT8-1586360075325)(media/15414898062564/15818728827852.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUUjlnE6-1586360075326)(media/15414898062564/15818729092686.jpg)]
本文围绕线程同步问题展开,介绍了OSSpinLock、os_unfair_lock、pthread_mutex等多种线程同步方案,分析了它们的特点和使用场景。还对各方案进行了性能比较,探讨了自旋锁和互斥锁的适用情况,最后给出了iOS中“多读单写”场景的读写安全方案。

被折叠的 条评论
为什么被折叠?



