第四章 并發(fā)編程

4.1 線程

  • 線程是運(yùn)行時(shí)執(zhí)行的一組指令序列
  • 每個(gè)進(jìn)程至少應(yīng)包含一個(gè)線程
  • 在iOS中,進(jìn)程啟動(dòng)時(shí)的主要線程通常稱作主線程
  • 所有的UI元素都需要在主線程中創(chuàng)建和管理
  • Cocoa編程不允許其他線程更新UI元素
  • 涉及到UI操作的嵌屎,都會(huì)將上下文鞋換到主線程再更新UI

4.2 線程開銷

  • 線程不僅有創(chuàng)建時(shí)的時(shí)間開銷,還會(huì)消耗內(nèi)核的內(nèi)存
  • 每個(gè)線程大約消耗1KB的內(nèi)核內(nèi)存空間
  • 這塊內(nèi)存用于存儲(chǔ)與線程有關(guān)的數(shù)據(jù)結(jié)構(gòu)和屬性哥放,此處無法被分頁
  • 主線程的棧空間為1M吠式,而且無法修改
  • 所有的二級線程默認(rèn)分配到512kb的棧空間
  • 完整的棧并不會(huì)立即創(chuàng)建出來,實(shí)際的椂媪郏空間大小會(huì)隨著使用而增長,因此即使主線程有1MB的椇干玻空間某個(gè)時(shí)間點(diǎn)的實(shí)際椣等危空間很可能要小很多
  • 在線程啟動(dòng)前恳蹲,椗翱椋空間的大小可以被改變,椉卫伲空間的最小值為16KB贺奠,而且其數(shù)值必須是4KB的倍數(shù)
  • iPhone 6 plus iOS 8.4 創(chuàng)建線程耗時(shí)4-5毫秒
  • 啟動(dòng)線程的耗時(shí)5-100毫秒,平均29毫秒错忱,開銷主要來源于上下文切換

4.3 GCD

  • GCD線程池中儡率,線程上限是64個(gè)

4.4 操作與隊(duì)列

  • NSOperation封裝了一個(gè)任務(wù)以及和任務(wù)相關(guān)的數(shù)據(jù)和代碼,而NSOperationQueue以先入先出的順序控制這一類任務(wù)的執(zhí)行
  • NSOperation和NSOperationQueue都提供控制線程個(gè)數(shù)的能力以清,可以控制隊(duì)列的個(gè)數(shù)也能控制每個(gè)隊(duì)列的線程個(gè)數(shù)
  • GCD:

    1.抽象程度最高

    2.兩種隊(duì)列開箱即用:main和global

    3.可以創(chuàng)建更多的隊(duì)列

    4.可以請求獨(dú)占(dispatch_barrier_sync和dispatch_barrier_async)

    5.基于線程管理

    6.硬性限制創(chuàng)建64個(gè)線程
  • NSOperationQueue:

    1.無默認(rèn)隊(duì)列

    2.應(yīng)用管理自己創(chuàng)建的隊(duì)列

    3.隊(duì)列是優(yōu)先級隊(duì)列

    4.操作可以有不同的優(yōu)先級(queuePriority屬性)

    5.使用cancel消息可以取消操作儿普,注:cancel只是標(biāo)記,如果操作已經(jīng)開始執(zhí)行掷倔,則可能會(huì)繼續(xù)執(zhí)行下去

    6.可以等待某個(gè)操作執(zhí)行完畢
  • NSThread:

    1.低級別構(gòu)造眉孩,最大化控制

    2.應(yīng)用創(chuàng)建并管理線程

    3.應(yīng)用創(chuàng)建并管理線程池

    4.應(yīng)用啟動(dòng)線程

    5.線程可以擁有優(yōu)先級,操作系統(tǒng)會(huì)根據(jù)優(yōu)先級調(diào)度他們的執(zhí)行

    6.無直接API用于等待線程完成,需要使用互斥量(NSLock)和自定義代碼
  • NSOperationQueue是多核安全

4.5.1 原子屬性

  • 線程安全通俗的理解為:多個(gè)線程并行執(zhí)行勒葱,不會(huì)產(chǎn)生任何副作用
  • 標(biāo)記為atomic只能阻止并行修改 ,并不能保證線程安全

4.5.2 同步塊

  • 使用@synchronized保證了任何時(shí)候都只能被一個(gè)線程執(zhí)行浪汪,使用如下:
@synchronized(instance){
        
}

4.5.3 鎖

  • 鎖可以認(rèn)為是低級別工具,atomic和@synchronized為高級封裝(抽象)
- (instancetype)init {
    self = [super init];
    if (self) {
        self -> lock  = [NSLock new];
        self -> reLock = [NSRecursiveLock new];
    }
    return self;
}
- (void)test {
    [self->lock lock];
    //線程安全的代碼
    [self->lock unlock];
}
  • 注意死鎖:
- (void)test {
    [self->lock lock];
    //線程安全的代碼
    NSLog(@"test");
    [self test1];
    [self->lock unlock];
}

- (void)test1 {
    //會(huì)死鎖
    [self->lock lock];
    NSLog(@"test1");
    [self->lock unlock];
}
  • 避免上述情況凛虽,可以使用遞歸鎖
- (void)test2 {
    [self->reLock lock];
    //線程安全的代碼
    NSLog(@"test2");
    [self test3];
    [self->reLock unlock];
}

- (void)test3 {
    [self->reLock lock];
    //線程安全的代碼
    NSLog(@"test3");
    [self->reLock unlock];
}
  • NSCondition:
  • 生產(chǎn)者死遭、消費(fèi)者
@interface Producer:NSObject

@property (nonatomic, strong) NSCondition *condition;
@property (nonatomic, strong) NSMutableArray *collector;
@property (nonatomic, assign) BOOL shouldProduce;

- (instancetype)initWithCondition:(NSCondition *)condition collector:(NSMutableArray *)collector;
- (void)produce;

@end

@implementation Producer

- (instancetype)initWithCondition:(NSCondition *)condition collector:(NSMutableArray *)collector {
    if (self = [super init]) {
        self.condition = condition;
        self.collector = collector;
        self.shouldProduce = NO;
    }
    return self;
}

- (void)produce {
    self.shouldProduce = YES;
    while (self.shouldProduce) {
        [self.condition lock];
        if (self.collector.count) {
            [self.condition wait];
        }
        [self.collector addObject:@"x"];
        [self.collector addObject:@"x"];
        NSLog(@"produce");
        [self.condition signal];
        [self.condition unlock];
    }
}

@end

@interface Customer:NSObject

@property (nonatomic, strong) NSCondition *condition;
@property (nonatomic, strong) NSMutableArray *collector;
@property (nonatomic, assign) BOOL shouldConsume;

- (instancetype)initWithCondition:(NSCondition *)condition collector:(NSMutableArray *)collector;
- (void)consume;

@end

@implementation Customer

- (instancetype)initWithCondition:(NSCondition *)condition collector:(NSMutableArray *)collector {
    if (self = [super init]) {
        self.condition = condition;
        self.collector = collector;
        self.shouldConsume = NO;
    }
    return self;
}

- (void)consume {
    self.shouldConsume = YES;
    while (self.shouldConsume) {
        [self.condition lock];
        if (self.collector.count) {
            [self.condition wait];
        }
        [self.collector removeObjectAtIndex:0];
        NSLog(@"consume");
        [self.condition signal];
        [self.condition unlock];
    }
}

@end

4.5.4 將讀寫鎖應(yīng)用于并發(fā)讀寫

  • 并行讀取,寫入互斥的一種機(jī)制--讀寫鎖
  • 可以用(dispatch_barrier_sync或dispatch_barrier_async)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凯旋,一起剝皮案震驚了整個(gè)濱河市呀潭,隨后出現(xiàn)的幾起案子钉迷,更是在濱河造成了極大的恐慌,老刑警劉巖钠署,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篷牌,死亡現(xiàn)場離奇詭異,居然都是意外死亡踏幻,警方通過查閱死者的電腦和手機(jī)枷颊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來该面,“玉大人夭苗,你說我怎么就攤上這事「糇海” “怎么了题造?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猾瘸。 經(jīng)常有香客問我界赔,道長,這世上最難降的妖魔是什么牵触? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任淮悼,我火速辦了婚禮,結(jié)果婚禮上揽思,老公的妹妹穿的比我還像新娘袜腥。我一直安慰自己,他們只是感情好钉汗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布羹令。 她就那樣靜靜地躺著,像睡著了一般损痰。 火紅的嫁衣襯著肌膚如雪福侈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天卢未,我揣著相機(jī)與錄音肪凛,去河邊找鬼。 笑死尝丐,一個(gè)胖子當(dāng)著我的面吹牛显拜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播爹袁,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼远荠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了失息?” 一聲冷哼從身側(cè)響起譬淳,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤档址,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后邻梆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體守伸,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年浦妄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尼摹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剂娄,死狀恐怖蠢涝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阅懦,我是刑警寧澤和二,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站耳胎,受9級特大地震影響惯吕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怕午,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一废登、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诗轻,春花似錦钳宪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搔体。三九已至恨樟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疚俱,已是汗流浹背劝术。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呆奕,地道東北人养晋。 一個(gè)月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像梁钾,于是被迫代替她去往敵國和親绳泉。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評論 2 350

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

  • Object C中創(chuàng)建線程的方法是什么姆泻?如果在主線程中執(zhí)行代碼零酪,方法是什么冒嫡?如果想延時(shí)執(zhí)行代碼、方法又是什么四苇? 1...
    AlanGe閱讀 1,722評論 0 17
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,856評論 25 707
  • 從三月份找實(shí)習(xí)到現(xiàn)在孝凌,面了一些公司,掛了不少月腋,但最終還是拿到小米蟀架、百度、阿里榆骚、京東辜窑、新浪、CVTE寨躁、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,218評論 11 349
  • 走進(jìn) 煙雨迷蒙的西塘 踏著千年的青石板路 迷蒙里 悠長的小巷深處 你的笑臉 一如夢里若即若離 所有的愛戀 彷徨 都...
    zero007閱讀 247評論 18 11
  • 數(shù)組 length屬性取得Array的長度:請注意穆碎,直接給Array的length賦一個(gè)新的值會(huì)導(dǎo)致Array大小...
    傲嬌的泰迪閱讀 151評論 0 0