iOS多线程与锁
多線程方案
pthread:一套C語言通用多線程API,跨平臺(tái),使用難度較大,需要開發(fā)者管理生命周期,iOS中幾乎用不到
NSThread:基于pthread的封裝,面向?qū)ο?#xff0c;同樣需要開發(fā)者管理生命周期,iOS中偶爾使用
GCD:能充分利用設(shè)備多核,提高效率,C語言API,自動(dòng)管理生命周期,iOS經(jīng)常使用
NSOperation:基于GCD的封裝,使用更加面向?qū)ο?#xff0c;OC語言,自動(dòng)管理生命周期,iOS經(jīng)常使用
以上方案的使用方法,這里不展開做介紹,本篇文章主要回顧iOS中鎖相關(guān)知識(shí)。
多線程安全隱患
當(dāng)多個(gè)線程訪問同一塊資源時(shí),容易引發(fā)數(shù)據(jù)安全問題。常見的場(chǎng)景:銀行存取錢的計(jì)算,多窗口售票等等,都映射到多線程的安全隱患。
舉個(gè)例子:
當(dāng)整型17被線程A和線程B先后讀取并進(jìn)行了+1操作,理論上最后得到的結(jié)果應(yīng)該是19,因?yàn)檫M(jìn)行了兩次+1,但是結(jié)果就出現(xiàn)了異常,這就是數(shù)據(jù)錯(cuò)亂。解決方案就是使用線程同步技術(shù),給定先后次序進(jìn)行操作,常見的線程同步技術(shù)就是加鎖。
加鎖后保證僅有一條線程對(duì)17進(jìn)行讀和寫,待線程操作完成解鎖后后面線程才可進(jìn)行讀寫操作,這樣一來得到的數(shù)據(jù)就正確了。
線程同步方案
OSSpinLock:自旋鎖,等待鎖的線程會(huì)處于忙等狀態(tài),一直占用CPU資源,目前已經(jīng)不再安全,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題。
os_unfair_lock:用于取代不安全的OSSpinLock,iOS10開始支持,并且等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài),而不是忙等狀態(tài),一定程度上節(jié)省CPU資源,使用需要導(dǎo)入<os/lock.h>
pthread_mutex:互斥鎖,等待鎖的線程會(huì)處于休眠狀態(tài),需導(dǎo)入<pthread.h>
普通鎖:
遞歸鎖:
條件鎖:
NSLock:是對(duì)mutex普通鎖的封裝,使用更加面向?qū)ο?/p>
@protocol NSLocking
- (void)lock;
- (void)unlock;
@end
@interface NSLock:NSObject< NSLocking>
- (BOOL)tryLock;
- (BOOL)lockBeforeDate:(NSDate *)limit;
@end
// 初始化化鎖
NSLock *lock = [NSLock new];
NSRecursiveLock:是對(duì)mutex遞歸鎖的封裝,API與NSLock基本一致
NSCondition:是對(duì)mutex和cond的封裝
NSConditionLock:是對(duì)NSCondition的進(jìn)一步封裝
@interface NSConditionLock : NSObject <NSLocking> { @privatevoid *_priv; } - (instancetype)initWithCondition:(NSInteger)condition; @property (readonly) NSInteger condition; - (void)lockWhenCondition:(NSInteger)condition; - (BOOL)tryLock; - (BOOL)tryLockWhenCondition:(NSInteger)condition; - (void)unlockWithCondition:(NSInteger)condition; - (BOOL)lockBeforeDate:(NSDate *)limit; - (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit; @property (nullable, copy) NSString *name; @enddispatch_semaphore:信號(hào)量,可以控制并發(fā)訪問最大數(shù)量,信號(hào)量初始化值為1代表同時(shí)只能有1條線程訪問資源用于確保線程同步。
//信號(hào)量初始值 int value = 1 //初始化信號(hào)量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(value); //如果信號(hào)量值<=0,當(dāng)前線程就會(huì)進(jìn)入休眠等待,直到信號(hào)量>0 //如果當(dāng)前信號(hào)量>0 就減1,然后執(zhí)行后面代碼 dispatch_semphore_wait(semaphore,DISPATCH_TIME_FOREVER) //讓信號(hào)量值+1 dispatch_semphore_signal(semaphore)@synchronized:是對(duì)mutex封裝,@synchronized(obj)內(nèi)部生成obj對(duì)應(yīng)的遞歸鎖,然后進(jìn)行加鎖解鎖操作。
自旋鎖和互斥鎖的比較
什么情況下使用自旋鎖:
1、預(yù)計(jì)線程等待鎖的時(shí)間很短
2、多核處理器
3、CPU資源不緊張
4、加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用,但是很少出現(xiàn)競(jìng)爭(zhēng)資源情況
什么情況下使用互斥鎖:
1、預(yù)計(jì)線程等待鎖的時(shí)間比較長
2、單核處理器
3、臨界區(qū)有IO操作
4、臨界區(qū)競(jìng)爭(zhēng)非常激烈
5、臨界區(qū)代碼復(fù)雜或者循環(huán)量大
總結(jié)
- 上一篇: 揭秘天猫双11背后:20万商家600万张
- 下一篇: IT企业专利工程师之三——计算机技术领域