一、自旋鎖和互斥鎖區(qū)別
自旋鎖: 忙等待
路鹰。即在訪問被鎖資源時(shí)贷洲,調(diào)用者線程不會(huì)休眠,而是不停循環(huán)在那里晋柱,直到被鎖資源釋放
互斥鎖: 會(huì)休眠
优构。即在訪問被鎖資源時(shí),調(diào)用者線程會(huì)休眠雁竞,此時(shí)cpu可以調(diào)度其它線程工作钦椭,直到被鎖資源釋放,此時(shí)會(huì)喚醒休眠線程浓领。
二者相同點(diǎn):
都能保證同一時(shí)間只有一個(gè)線程訪問共享資源玉凯。都能保證線程安全。
二联贩、OSSpinLock(自旋鎖)
OSSpinLock叫做”自旋鎖”漫仆,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài),一直占用著CPU資源
-
目前已經(jīng)不再安全泪幌,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題
- 如果等待鎖的線程優(yōu)先級(jí)較高盲厌,它會(huì)一直占用著CPU資源署照,優(yōu)先級(jí)低的線程就無法釋放鎖
-
需要導(dǎo)入頭文件#import <libkern/OSAtomic.h>
備注:
一定要對(duì)同一把鎖進(jìn)行加鎖
三、os_unfair_lock(互斥鎖)
- os_unfair_lock用于取代不安全的OSSpinLock 吗浩,從iOS10開始才支持
- 從底層調(diào)用看建芙,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài),并非忙等
- 需要導(dǎo)入頭文件#import <os/lock.h>
四懂扼、pthread_mutex(互斥鎖)
- 是跨平臺(tái)的(凡是帶有pthread)
- mutex叫做”互斥鎖”禁荸,等待鎖的線程會(huì)處于休眠狀態(tài)
-
需要導(dǎo)入頭文件#import <pthread.h>
備注:
pthread_mutex可以有3個(gè)狀態(tài),一般常用的是2個(gè)狀態(tài):normal和recursive
- normal(互斥鎖)
- recursive(遞歸鎖)
五阀湿、pthread_mutex-遞歸鎖
六赶熟、pthread_mutex – 條件
七、NSLock(互斥鎖)
-
NSLock是對(duì)mutex普通鎖的封裝
八陷嘴、NSRecursiveLock(遞歸鎖)
- NSRecursiveLock也是對(duì)mutex遞歸鎖的封裝映砖,API跟NSLock基本一致
九、NSCondition(條件鎖)
-
NSCondition是對(duì)mutex和cond的封裝
十灾挨、NSConditionLock(條件鎖)
-
NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝邑退,可以設(shè)置具體的條件值
十一、dispatch_semaphore
- semaphore叫做”信號(hào)量”
- 信號(hào)量的初始值劳澄,可以用來控制線程并發(fā)訪問的最大數(shù)量
- 信號(hào)量的初始值為1地技,代表同時(shí)只允許1條線程訪問資源,保證線程同步
十二浴骂、dispatch_queue
-
直接使用GCD的串行隊(duì)列乓土,也是可以實(shí)現(xiàn)線程同步的
十三宪潮、@synchronized
- @synchronized是對(duì)mutex遞歸鎖的封裝
- 源碼查看:objc4中的objc-sync.mm文件
-
@synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的遞歸鎖溯警,然后進(jìn)行加鎖、解鎖操作
小結(jié):
- OSSpinLock效率最高狡相,但是已經(jīng)不再安全梯轻,使用os_unfair_lock(ios10.0以上),最優(yōu)方案是使用dispatch_semaphore
- 遞歸鎖比非遞歸鎖要耗時(shí)尽棕,但是當(dāng)保護(hù)資源需要遞歸調(diào)用時(shí)喳挑,就要使用遞歸鎖:pthread_mutex-遞歸鎖、NSRecursiveLock滔悉、synchronized
- NSLock和NSCondition效率可以伊诵,使用也比較簡(jiǎn)單
- dispatch_semaphore和自旋鎖效率接近,使用簡(jiǎn)單回官,一般推薦使用dispatch_semaphore進(jìn)行資源保護(hù)
- NSConditionLock是條件鎖曹宴,內(nèi)部有個(gè)
condition
狀態(tài),滿足這個(gè)condition
才會(huì)獲取到鎖歉提,否則會(huì)阻塞等待笛坦。效率比較低效区转,一般不使用。
十四版扩、自旋鎖废离、互斥鎖比較
14.1、什么情況使用自旋鎖比較劃算礁芦?
- 預(yù)計(jì)線程等待鎖的時(shí)間很短
- 加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用蜻韭,但競(jìng)爭(zhēng)情況很少發(fā)生
- CPU資源不緊張
- 多核處理器
14.2、什么情況使用互斥鎖比較劃算柿扣?
- 預(yù)計(jì)線程等待鎖的時(shí)間較長(zhǎng)
- 單核處理器
- 臨界區(qū)有IO操作
- 臨界區(qū)代碼復(fù)雜或者循環(huán)量大
- 臨界區(qū)競(jìng)爭(zhēng)非常激烈
十五湘捎、atomic誤解
只能保證set和get方法是原子操作,是安全的窄刘。但是窥妇,你使用對(duì)象時(shí),這個(gè)是不受保護(hù)的
十六娩践、高效的讀寫
使用dispatch_barrier_async
活翩。
十七、并發(fā)數(shù)組崩潰解決方案
- GCD的并發(fā)隊(duì)列翻伺,使用
dispatch_barrier_async
- 數(shù)組的讀寫同時(shí)增加
互斥鎖
(保持最小加鎖原則)
十八材泄、小知識(shí)點(diǎn)
- GCD并發(fā)隊(duì)列子線程任務(wù)過多(超過64個(gè)),會(huì)導(dǎo)致主線程死鎖吨岭。
- 子線程不使用自動(dòng)釋放池:不會(huì)導(dǎo)致內(nèi)存泄漏
- 正確休眠子線程:有事情就工作拉宗,否則休眠,并且隨時(shí)可以退出