iOS中的線程同步方案

前提簡(jiǎn)述:

常用的線程方案有Pthread色乾,NSThread, GCD,NSOperation。以下是比較:
pthread : 是一套通用的C語(yǔ)言多線程API,適用于Unix \ Linux\ Windows等系統(tǒng),可跨平臺(tái)\可移植性号显,學(xué)習(xí)難度大。線程生命周期需要程序員管理躺酒。

NSThread: 是OC語(yǔ)言押蚤,使用更加面向?qū)ο螅苯硬僮骶€程對(duì)象羹应,程序員需要管理生命周期揽碘。

GCD: 可替代NSThread等線程技術(shù),C語(yǔ)言實(shí)現(xiàn)园匹,系統(tǒng)自動(dòng)管理钾菊。

NSOperation: 基于GCD的封裝成OC對(duì)象,比GCD多了一些更簡(jiǎn)單實(shí)用的功能偎肃,使用更加面向?qū)ο螅到y(tǒng)自動(dòng)管理線程生命周期

另附上兩個(gè)案例:

?dispatch_async(dispatch_get_global_queue(0, 0), ^{

? ? ? ? NSLog(@"1");

? ? ? ? [self performSelector:@selector(test) withObject:nil afterDelay:0];

? ? ? ? NSLog(@"3");

? ? })

-(void)test { NSLog(@"2") ;}

打印結(jié)果是:1浑此、3累颂。

原因:performSelector…afterDelay是向runloop中添加了一個(gè)timer定時(shí)器,子線程中默認(rèn)是沒有啟動(dòng)runloop的凛俱,所以不會(huì)執(zhí)行紊馏。

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event {

? ? NSThread*thread = [[NSThreadalloc]initWithBlock:^{

? ? ? ? NSLog(@"1");

? ? }];

? ? [threadstart];

? ? BOOLisOk =true;

? ? // isOk 設(shè)置為YES時(shí),會(huì)導(dǎo)致crash蒲犬, 因?yàn)樵谧泳€程runloop未開啟朱监,block執(zhí)行完畢后,Threadj即退出原叮;會(huì)提示此信息:performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform'

? ? // 設(shè)置為NO赫编,test不執(zhí)行。

? ? [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:isOk];

}

多線程存在安全隱患奋隶,同一個(gè)數(shù)據(jù)可能會(huì)被多個(gè)線程共享擂送,也就是多個(gè)線程可能會(huì)訪問同一塊資源,當(dāng)多個(gè)線程訪問同一塊資源時(shí)唯欣,很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問題嘹吨。這種情況,我們需要使用線程同步技術(shù)(同步境氢,就是協(xié)同步調(diào)蟀拷,按預(yù)定的先后次序進(jìn)行)解決碰纬。常用的方式是加鎖。

iOS線程同步方案:

1,?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>

OSSpinLock lock =?OS_SPINLOCK_INIT;

OSSpinLockLock(&_moneyLock);

//coding here

?OSSpinLockUnlock(&_moneyLock);

2,?os_unfair_lock

nos_unfair_lock用于取代不安全的OSSpinLock ,從iOS10開始才支持

n從底層調(diào)用看炕柔,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài)酌泰,并非忙等

n需要導(dǎo)入頭文件#import<os/lock.h>

os_unfair_lock lock =?OS_UNFAIR_LOCK_INIT;

os_unfair_lock_lock(&_ticketLock);

// coding here

os_unfair_lock_unlock(&_ticketLock);

3,?pthread_mutex

mutex叫做”互斥鎖”,等待鎖的線程會(huì)處于休眠狀態(tài)匕累。需要導(dǎo)入頭文件#import<pthread.h>

{ ? ?// 靜態(tài)初始化

? ? pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

? ??// 初始化屬性

? ? pthread_mutexattr_t attr;

? ? pthread_mutexattr_init(&attr);

? ? pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);

// ? ?初始化鎖

? ? pthread_mutex_init(mutex, &attr);

// ? 銷毀屬性

? ? pthread_mutexattr_destroy(&attr);

? ? // 初始化鎖 ?NULL表示默認(rèn)屬性

? ? pthread_mutex_init(mutex, NULL);

}

{

?????pthread_mutex_lock(&_ticketMutex);

????//coding here...

????pthread_mutex_unlock(&_ticketMutex);

}

- (void)dealloc{

? ? pthread_mutex_destroy(&mutex);

}

4, pthread_mutex 遞歸鎖

用法和3類似瓤檐,上述pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)

5, pthread_mutex – 條件鎖

使用方法展示:

?pthread_mutex_t mutex;

?pthread_mutex_init(&mutex, NULL); //NULL表示使用默認(rèn)屬性

? // 初始化條件

?pthread_cond_t condition;

?pthread_cond_init(&condition, NULL);

// 等待條件(進(jìn)入休眠,釋放mutex鎖惫东; 被喚醒后揩局,會(huì)再次對(duì)mutex加鎖)

pthread_cond_wait(&condition, &mutex);

//激活一個(gè)等待該條件的線程

pthread_cond_signal(&condition);

//激活所有等待該條件的線程

pthread_cond_broadcast(&condition);

- (void) del{

????pthread_mutex_lock(&_mutex);

? ? pthread_cond_wait(&_cond, &_mutex);

????// coding here

? ? pthread_mutex_unlock(&_mutex);

}

-(void)append {

????pthread_mutex_lock(&_mutex);

????// coding here

? ? pthread_cond_signal(&_cond);??// 信號(hào)

? ? pthread_mutex_unlock(&_mutex);

}

- (void)dealloc {

? ? pthread_mutex_destory(&mutex);

? ? pthread_cond_destory(&condition);
}

6,NSLock

NSLock是對(duì)mutex普通鎖的封裝, 遵守NSLocking協(xié)議

7,NSRecursiveLock

NSRecursiveLock也是對(duì)mutex遞歸鎖的封裝,API跟NSLock基本一致

8炼蹦,NSCondition

NSCondition是對(duì)mutex和cond的封裝羡宙,使用演示如下:

NSCondition *condition = [[NSCondition alloc] init];

- (void)del{

? ? [condition lock];

? ? [condition wait];??// 等待

? ? // coding here

? ? [condition unlock];

}

- (void)add{

? ? [self.condition lock];

????// coding here

? ??[self.condition broadcast];

? ? [self.condition unlock];

}

9,?NSConditionLock

NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置具體的條件值掐隐。簡(jiǎn)列使用如下:

int start = 0; 設(shè)置某個(gè)啟動(dòng)條件

NSConditionLock *conditionLock =?[[NSConditionLock alloc] initWithCondition: start];

[conditionLock lock];

[conditionLock lockWhenCondition: some];

[conditionLock unlockWithCondition:some];

[conditionLock unlock];

10狗热,dispatch_semaphore

semaphore叫做”信號(hào)量”,信號(hào)量的初始值虑省,可以用來控制線程并發(fā)訪問的最大數(shù)量匿刮,信號(hào)量的初始值為1,代表同時(shí)只允許1條線程訪問資源探颈,可以用來保證線程同步熟丸。

dispatch_semaphore_t semaphore = dispatch_semaphore_create(x);

//當(dāng)信號(hào)量的值<=0,當(dāng)前線程就會(huì)進(jìn)入休眠等待(直到信號(hào)量的值大于0)

//如果信號(hào)量的值>0,就減1,然后執(zhí)行后面的代碼

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

dispatch_semaphore_signal(semaphore);

11伪节,?dispatch_queue

直接使用GCD的串行隊(duì)列光羞,也是可以實(shí)現(xiàn)線程同步的。

12架馋,@synchronized

@synchronized是對(duì)mutex遞歸鎖的封裝狞山;@synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的遞歸鎖,然后進(jìn)行加鎖叉寂、解鎖操作萍启。

@synchronized (token) {}

13,?atomic用于保證屬性setter、getter的原子性操作,相當(dāng)于在getter和setter內(nèi)部加了線程同步的鎖,?它并不能保證使用屬性的過程是線程安全的勘纯。

線程同步方案性能比較,性能從高到低排序依次是:

os_unfair_lock >?OSSpinLock >?dispatch_semaphore >?pthread_mutex >?pdispatch_queue(DISPATCH_QUEUE_SERIAL) > ?NSLock >?NSCondition >?ppthread_mutex(recursive) >?NSRecursiveLock >?NSConditionLock >?@synchronized

自旋鎖局服、互斥鎖比較:

a, 什么情況使用自旋鎖比較劃算?

預(yù)計(jì)線程等待鎖的時(shí)間很短

加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用驳遵,但競(jìng)爭(zhēng)情況很少發(fā)生

CPU資源不緊張

多核處理器

b,什么情況使用互斥鎖比較劃算淫奔?

預(yù)計(jì)線程等待鎖的時(shí)間較長(zhǎng)

單核處理器

臨界區(qū)有IO操作

臨界區(qū)代碼復(fù)雜或者循環(huán)量大

臨界區(qū)競(jìng)爭(zhēng)非常激烈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市堤结,隨后出現(xiàn)的幾起案子唆迁,更是在濱河造成了極大的恐慌,老刑警劉巖竞穷,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唐责,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瘾带,警方通過查閱死者的電腦和手機(jī)鼠哥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來看政,“玉大人朴恳,你說我怎么就攤上這事≡黍迹” “怎么了于颖?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)嚷兔。 經(jīng)常有香客問我恍飘,道長(zhǎng),這世上最難降的妖魔是什么谴垫? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮母蛛,結(jié)果婚禮上翩剪,老公的妹妹穿的比我還像新娘。我一直安慰自己彩郊,他們只是感情好前弯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秫逝,像睡著了一般恕出。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上违帆,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天浙巫,我揣著相機(jī)與錄音,去河邊找鬼。 笑死的畴,一個(gè)胖子當(dāng)著我的面吹牛渊抄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丧裁,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼护桦,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了煎娇?” 一聲冷哼從身側(cè)響起二庵,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缓呛,沒想到半個(gè)月后催享,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡强经,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年睡陪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匿情。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兰迫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炬称,到底是詐尸還是另有隱情汁果,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布玲躯,位于F島的核電站据德,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏跷车。R本人自食惡果不足惜棘利,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朽缴。 院中可真熱鬧善玫,春花似錦、人聲如沸密强。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)或渤。三九已至系冗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間薪鹦,已是汗流浹背掌敬。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工惯豆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涝开。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓循帐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親舀武。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拄养,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 鎖是一種同步機(jī)制,用于多線程環(huán)境中對(duì)資源訪問的限制iOS中常見鎖的性能對(duì)比圖(摘自:ibireme): iOS鎖的...
    LiLS閱讀 1,516評(píng)論 0 6
  • 線程同步方案 OSSpinLock 自旋鎖 os_unfair_lock pthread_mutex dispat...
    那位小姐閱讀 1,643評(píng)論 0 19
  • 一银舱、簡(jiǎn)介:多線程在之前進(jìn)行過一篇詳細(xì)的基礎(chǔ)博客 iOS多線程 二瘪匿、多線程的基礎(chǔ)知識(shí)回顧 1.1、iOS中的常見多線...
    IIronMan閱讀 893評(píng)論 0 4
  • Q:為什么出現(xiàn)多線程寻馏? A:為了實(shí)現(xiàn)同時(shí)干多件事的需求(并發(fā))棋弥,同時(shí)進(jìn)行著下載和頁(yè)面UI刷新。對(duì)于處理器诚欠,為每個(gè)線...
    幸福相依閱讀 1,582評(píng)論 0 2
  • 轉(zhuǎn)載自:http://www.reibang.com/p/938d68ed832c# 一顽染、前言 前段時(shí)間看了幾個(gè)...
    cafei閱讀 4,540評(píng)論 1 12