多線程

主要內(nèi)容:
1 GCD隊(duì)列循環(huán)等待镀梭、多讀單寫、組任務(wù)
2 NSOpertaion優(yōu)點(diǎn)
3 NSThread實(shí)現(xiàn)原理
4 常用鎖的區(qū)別

GCD

同步串行

在viewDidLoad中有下面一段代碼

 dispatch_sync(dispatch_get_main_queue(), ^{
        [self doSomething];
   });

很多人說(shuō)這會(huì)造成死鎖。其實(shí)更準(zhǔn)確的說(shuō)法是:主隊(duì)列循環(huán)等待造成死鎖疆液。


主隊(duì)列

主隊(duì)列是一個(gè)串行隊(duì)列偿警,viewDidLoad提交到了主線程執(zhí)還未執(zhí)行完畢负间,此時(shí)再同步提交doSomething到主線程相艇。viewDidLoad被阻塞等待doSomething返回隙姿,而doSomething是后提交的任務(wù),必須等前一個(gè)任務(wù)viewDidLoad執(zhí)行完畢后厂捞,才能執(zhí)行。這就是隊(duì)列循環(huán)等待造成的死鎖队丝。
在viewDidLoad中代碼改為如下

_serialQueue = dispatch_queue_create("thread_name", DISPATCH_QUEUE_SERIAL);
dispatch_sync(_serialQueue, ^{
        [self doSomething];
 });

這樣會(huì)不會(huì)造成靡馁,隊(duì)列循環(huán)等待呢?答案是:不會(huì)机久。



這里需要注意:只要是同步方式提交臭墨,不管是提交到串行隊(duì)列還是并發(fā)隊(duì)列,都是在當(dāng)前線程執(zhí)行膘盖。
所以,如圖所示不會(huì)造成死鎖胧弛,并且doSomething會(huì)在主線程中執(zhí)行尤误。

同步提交到并發(fā)隊(duì)列

NSLog(@"1");
dispatch_sync(globalQueue, ^{
        NSLog(@"2");
        dispatch_sync(globalQueue, ^{
            NSLog(@"3");
        });
         NSLog(@"4");
  });
  NSLog(@"5");

并發(fā)隊(duì)列特點(diǎn):提交到隊(duì)列的block可以并發(fā)執(zhí)行。 打印結(jié)果12345

異步提交到并發(fā)隊(duì)列

 dispatch_async(dispatch_get_global_queue(0, 0), ^{
      NSLog(@"1");
      [self performSelector:@selector(printLog) withObject:nil afterDelay:0];
       NSLog(@"3");
 });
-(void)printLog
{
    NSLog(@"2");
}

結(jié)果是:1和3结缚。RunLoop在主線程是自動(dòng)創(chuàng)建的损晤,在子線程中是沒(méi)有創(chuàng)建的。performSelector:withObject:afterDelay: 方法關(guān)鍵是afterDelay相當(dāng)于創(chuàng)建了一個(gè)Timer提交到了RunLoop红竭。等待下一次RunLoop循環(huán)事件時(shí)執(zhí)行尤勋。而子線程中RunLoop根本就沒(méi)有創(chuàng)建。所以printLog也就不會(huì)執(zhí)行茵宪。

[self performSelector:@selector(printLog) withObject:nil];
[self performSelectorOnMainThread:@selector(printLog) withObject:nil waitUntilDone:YES];

請(qǐng)注意上面2個(gè)方法就是一個(gè)普通方法調(diào)用最冰。與帶afterDelay的有本質(zhì)區(qū)別。

dispatch_barrier_async()

提供了一種多讀單寫技術(shù)稀火,讀與讀可以并發(fā)暖哨,讀與寫是互斥的,寫和寫之間是互斥的凰狞。


#import "DataCenter.h"

@interface  DataCenter()
{
    dispatch_queue_t  _concurrent_queue;
    //用戶數(shù)據(jù)中心篇裁,可能有多個(gè)線程需要訪問(wèn)
    NSMutableDictionary *_dataCenterDict;
}

@end

@implementation DataCenter

-(id)init
{
    self = [super init];
    if(self){
        _concurrent_queue = dispatch_queue_create("read_write_queue", DISPATCH_QUEUE_CONCURRENT);
        _dataCenterDict = [NSMutableDictionary dictionary];
    }
    return self;
}

-(id)objectForKey:(NSString*)key
{
    __block id obj;
    //同步讀取指定數(shù)據(jù): 若果是線程A調(diào)用,那么子啊線程A中執(zhí)行服球。 若果是線程B調(diào)用茴恰,那么在線程B中執(zhí)行
    //由于是并發(fā)隊(duì)列,可以同時(shí)滿足多個(gè)線程同時(shí)調(diào)用斩熊。
    dispatch_sync(_concurrent_queue, ^{
        obj = [_dataCenterDict objectForKey:key];
    });
    return obj;
}

-(void)setObject:(id)obj forKey:(NSString*)key
{
    //異步調(diào)用柵欄設(shè)置數(shù)據(jù)
    dispatch_barrier_async(_concurrent_queue, ^{
        [_dataCenterDict setObject:obj forKey:key];
    });
}

NSOperation

優(yōu)點(diǎn)
1 添加依賴任務(wù)
2 任務(wù)執(zhí)行狀態(tài)控制
3 控制最大并發(fā)量

任務(wù)執(zhí)行狀態(tài)控制
isReady : 就緒
isExecuting: 執(zhí)行中
isFinished: 執(zhí)行完成
isCancelled: 已取消
只重寫main()方法往枣,系統(tǒng)控制任務(wù)狀態(tài),以及退出
重寫了start()方法粉渠,需要自己控制任務(wù)狀態(tài)
系統(tǒng)是怎樣移除一個(gè)isFinished=YES的NSOperation的分冈?KVO

NSThread

實(shí)現(xiàn)原理:內(nèi)部創(chuàng)建了一個(gè)pthread線程,當(dāng)執(zhí)行完main函數(shù)后霸株,系統(tǒng)會(huì)自動(dòng)退出雕沉。


@synchronized

一般在創(chuàng)建單例對(duì)象的時(shí)候使用,保證在多線程環(huán)境下創(chuàng)建對(duì)象唯一

atomic

屬性關(guān)鍵字去件,對(duì)被修飾對(duì)象進(jìn)行原子操作(不負(fù)責(zé)使用)

@property(atomic)NSMutableArray *array;
self.array = [NSMutableArray array]; //保證線程安全
[self.array addObject: obj]; //不保證線程安全
OSSpinLock

循環(huán)等待訪問(wèn)坡椒,不釋放當(dāng)前資源, 專門用于輕量級(jí)訪問(wèn),如+1尤溜,-1操作倔叼。如:引用計(jì)數(shù)

NSRecursiveLock

遞歸鎖可以重入

NSLock

互斥鎖,不可重入宫莱,上鎖解鎖丈攒,成對(duì)出現(xiàn)。

dispatch_semaphore_t
dispatch_semaphore_create(1);
dispatch_semaphore_wait(semphore,DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semaphore)
dispatch_semaphore_create()
struct semaphore {
    int value;
    List<thread> //相關(guān)線程
}

dispatch_semaphore_wait 檢測(cè)到S.value < 0 ,主動(dòng)阻塞自己

dispatch_semaphore_wait()
{
    S.value = S.value - 1;
    if S.value < 0  then Block(S.List);  
}

dispatch_semaphore_signal 檢查后巡验,去喚醒線程际插。對(duì)于線程來(lái)說(shuō),是一個(gè)被動(dòng)喚醒显设。

dispatch_semaphore_signal()
{
    S.value = S.value + 1;
    if(S.value <= 0) then wakeup(S.List)
}

總結(jié)

1 怎樣GCD實(shí)現(xiàn)多讀單寫框弛?
2 iOS提供了幾種多線程技術(shù),各自特點(diǎn)是什么敷硅?
3 NSOpertaion對(duì)象在Finished之后是怎樣從queue當(dāng)中移除的功咒?
4 你多用過(guò)那些鎖?結(jié)合實(shí)際談?wù)勀闶窃鯓訉?shí)現(xiàn)的绞蹦?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末力奋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子幽七,更是在濱河造成了極大的恐慌景殷,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澡屡,死亡現(xiàn)場(chǎng)離奇詭異猿挚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)驶鹉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門绩蜻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人室埋,你說(shuō)我怎么就攤上這事办绝。” “怎么了姚淆?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵孕蝉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我腌逢,道長(zhǎng)降淮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任搏讶,我火速辦了婚禮佳鳖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘媒惕。我一直安慰自己系吩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布吓笙。 她就那樣靜靜地躺著,像睡著了一般巾腕。 火紅的嫁衣襯著肌膚如雪面睛。 梳的紋絲不亂的頭發(fā)上絮蒿,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音叁鉴,去河邊找鬼土涝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛幌墓,可吹牛的內(nèi)容都是我干的但壮。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼常侣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蜡饵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起胳施,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤溯祸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后舞肆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焦辅,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年椿胯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筷登。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哩盲,死狀恐怖前方,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情种冬,我是刑警寧澤镣丑,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站娱两,受9級(jí)特大地震影響莺匠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜十兢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一趣竣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧旱物,春花似錦遥缕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春户秤,著一層夾襖步出監(jiān)牢的瞬間码秉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工鸡号, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留转砖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓鲸伴,卻偏偏與公主長(zhǎng)得像府蔗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汞窗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

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

  • 從哪說(shuō)起呢姓赤? 單純講多線程編程真的不知道從哪下嘴。杉辙。 不如我直接引用一個(gè)最簡(jiǎn)單的問(wèn)題模捂,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,774評(píng)論 1 17
  • GCD簡(jiǎn)介 GCD 是 libdispatch 的市場(chǎng)名稱,而 libdispatch 作為 Apple 的一個(gè)庫(kù)...
    獨(dú)木舟的木閱讀 1,256評(píng)論 0 5
  • 目錄 一蜘矢、基本概念1.多線程2.串行和并行狂男, 并發(fā)3.隊(duì)列與任務(wù)4.同步與異步5.線程狀態(tài)6.多線程方案 二、GC...
    BohrIsLay閱讀 1,588評(píng)論 5 12
  • NSThread 第一種:通過(guò)NSThread的對(duì)象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 805評(píng)論 0 3
  • 刺骨的寒風(fēng)呼呼的吹著品腹,漫長(zhǎng)的夏天終于過(guò)去了岖食。 秋天是冷的,但是路確是香氣逼人舞吭。學(xué)校里的桂花樹一排排立在寬闊的馬路上...
    小崔崔崔崔閱讀 387評(píng)論 0 1