iOS開發(fā)-10.多線程

  • 1.iOS中的常見多線程方案
    image
a) NSThread / GCD / NSOperation底層都是pthread

b) NSThread開啟線程方式
    1) 動(dòng)態(tài)實(shí)例化
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test:) object:nil];
thread.threadPriority = 1;  //設(shè)置線程的優(yōu)先級(jí)(0.0 - 1.0, 1.0最高級(jí))
[thread start];
    2) 靜態(tài)實(shí)例化
[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:nil];
    3) 隱式實(shí)例化
        3.1)
[self performSelectorOnMainThread:@selector(test:) withObject:nil waitUntilDone:YES];
  • 2.GCD的常用函數(shù)
a) GCD中有2個(gè)用來執(zhí)行任務(wù)的函數(shù)
    1) 用同步的方式執(zhí)行任務(wù)
    dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); // queue:隊(duì)列 block:任務(wù)
        1.1) dispatch_sync : 立馬在當(dāng)前線程同步執(zhí)行任務(wù),不執(zhí)行就不會(huì)往下走
    
    2) 用異步的方式執(zhí)行任務(wù)
    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
        2.1) dispatch_async : 不要求立馬在當(dāng)前線程同步執(zhí)行任務(wù),等上一個(gè)任務(wù)(也可能是整個(gè)外部的大函數(shù)執(zhí)行完畢)執(zhí)行完了再執(zhí)行

b) GCD源碼https://github.com/apple/swift-corelibs-libdispatch
  • 3.GCD的隊(duì)列
a) GCD的隊(duì)列可以分為2大類型
    1) 并發(fā)隊(duì)列(Concurrent Dispatch Queue)
        1.1) 可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))
        1.2) 并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效

b) 串行隊(duì)列(Serial Dispatch Queue)
    1) 讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))
    2) 主隊(duì)列是一種特殊的串行隊(duì)列
    
c) 隊(duì)列的特點(diǎn) : 排隊(duì),F(xiàn)IFO盹兢,F(xiàn)irst In First Out 先進(jìn)先出

d) Global Queue全局隊(duì)列的指針地址是相同的,而手動(dòng)創(chuàng)建的隊(duì)列則地址是不相同的
  • 4.容易混淆的術(shù)語
a) 同步和異步主要影響:能不能開啟新的線程
    1) 同步:在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
    2) 異步:在新的線程中執(zhí)行任務(wù)哥桥,具備開啟新線程的能力

b) 并發(fā)和串行主要影響:任務(wù)的執(zhí)行方式
    1) 并發(fā):多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行
    2) 串行:一個(gè)任務(wù)執(zhí)行完畢后佃扼,再執(zhí)行下一個(gè)任務(wù)
  • 5.各種隊(duì)列的執(zhí)行效果
    image
a) 使用sync函數(shù)往當(dāng)前串行隊(duì)列中添加任務(wù),會(huì)卡住當(dāng)前的串行隊(duì)列(產(chǎn)生死鎖)

b) performSelector:withObject:afterDelay: 
    1) 有afterDelay的方法都是跟Runloop有關(guān),相當(dāng)于添加了一個(gè)定時(shí)器到Runloop去執(zhí)行 所以你要看當(dāng)前執(zhí)行任務(wù)的線程有沒有Runloop
    2) 在主線程好時(shí)正常調(diào)用,但是會(huì)延遲,因?yàn)橹骶€程默認(rèn)就會(huì)開啟一個(gè)Runloop,延遲是因?yàn)橹骶€程的任務(wù)執(zhí)行順序是串行的,需要等上一個(gè)任務(wù)執(zhí)行完畢,可以理解為包裝該線程調(diào)用的{}范圍函數(shù)調(diào)用完畢,例如viewDidLoad方法調(diào)用完畢
    3) 但是在子線程卻不好使,直接不調(diào)用,因?yàn)樽泳€程沒有開啟Runloop來蔽⑼酰活
  • 6.隊(duì)列組的使用
a) 思考:如何用gcd實(shí)現(xiàn)以下功能
    1) 異步并發(fā)執(zhí)行任務(wù)1屡限、任務(wù)2
    2) 等任務(wù)1、任務(wù)2都執(zhí)行完畢后炕倘,再回到主線程執(zhí)行任務(wù)3
image
  • 7.多線程的安全隱患
a) 資源共享
    1) 1塊資源可能會(huì)被多個(gè)線程共享钧大,也就是多個(gè)線程可能會(huì)訪問同一塊資源
    2) 比如多個(gè)線程訪問同一個(gè)對(duì)象、同一個(gè)變量罩旋、同一個(gè)文件

b) 當(dāng)多個(gè)線程訪問同一塊資源時(shí)啊央,很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問題

c) 多線程安全隱患示例01 – 存錢取錢
image
d) 多線程安全隱患示例02 – 賣票
image
e) 多線程安全隱患分析
image
f) 多線程安全隱患的解決方案
    1) 解決方案:使用線程同步技術(shù)(同步,就是協(xié)同步調(diào)涨醋,按預(yù)定的先后次序進(jìn)行)
    2) 線程同步本質(zhì):是不能同時(shí)讓多條線程占用一個(gè)資源
    2) 常見的線程同步技術(shù)是:加鎖(所有線程都用同一把鎖)
    3) 鎖的原理:首先判斷這把鎖有沒有被人加過,沒有就會(huì)加鎖,有被加過,就會(huì)等待
image
  • 8.iOS中的線程同步方案
a) OSSpinLock(High-level-lock高級(jí)鎖)
    1) OSSpinLock叫做”自旋鎖”,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài)(相當(dāng)于執(zhí)行了一個(gè)do while循環(huán))一直占用著CPU資源
    2) iOS10.0開始不推薦使用,目前已經(jīng)不再安全瓜饥,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題(如果等待鎖的線程優(yōu)先級(jí)較高,它會(huì)一直占用著CPU資源浴骂,優(yōu)先級(jí)低的線程就無法釋放鎖,造成死鎖的現(xiàn)象)
    3) 需要導(dǎo)入頭文件#import <libkern/OSAtomic.h>
image
b) os_unfair_lock(Low-level-lock低級(jí)鎖)
    1) os_unfair_lock用于取代不安全的OSSpinLock 乓土,從iOS10開始才支持
    2) 從底層調(diào)用看,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài)溯警,并非忙等
    3) 需要導(dǎo)入頭文件#import <os/lock.h>
image
c) pthread_mutex(Low-level-lock低級(jí)鎖)
    1) mutex叫做”互斥鎖”帐我,等待鎖的線程會(huì)處于休眠狀態(tài)
    2) 需要導(dǎo)入頭文件#import <pthread.h>
image
    3) pthread_mutex – 遞歸鎖
        3.1) 遞歸鎖:允許用同一條線程對(duì)一把鎖進(jìn)行重復(fù)加鎖
image
    4) pthread_mutex – 條件
        4.1) 條件(等待條件,等不到條件就休眠,等待的時(shí)候解鎖,喚醒的時(shí)候加鎖,次數(shù)對(duì)等,一般用于線程之間的通信)
image
d) NSLock
    1) NSLock是對(duì)mutex普通鎖的封裝
image
e) NSRecursiveLock
    1) NSRecursiveLock是對(duì)mutex遞歸鎖的封裝,API跟NSLock基本一致
f) NSCondition
    1) NSCondition是對(duì)mutex和cond的封裝
    2) signal:信號(hào)發(fā)出的時(shí)機(jī),決定了后續(xù)代碼的執(zhí)行,因?yàn)樵诮怄i前和解鎖后
    3) signal:信號(hào)(單個(gè))和broadcast:廣播(多個(gè))的區(qū)別
image
g) NSConditionLock
    1) NSConditionLock是對(duì)NSCondition的進(jìn)一步封裝愧膀,可以設(shè)置具體的條件值
    2) 初始化不設(shè)置條件值的時(shí)候,默認(rèn)條件值就是0
    3) lock:直接加鎖谣光,不等條件值檩淋,如果沒有加鎖,那就加鎖
    4) lockWhenCondition:條件值為多少的時(shí)候才加鎖
    5) unlockWithCondition:解鎖并且設(shè)置條件值
    6) 在子線程執(zhí)行的任務(wù),可以達(dá)到依賴的效果
image
h) dispatch_semaphore
    1) semaphore叫做”信號(hào)量”
    2) 信號(hào)量的初始值萄金,可以用來控制線程并發(fā)訪問的最大數(shù)量
    3) 信號(hào)量的初始值為1蟀悦,代表同時(shí)只允許1條線程訪問資源,保證線程同步
image
i) dispatch_queue
    1) 直接使用GCD的串行隊(duì)列氧敢,也是可以實(shí)現(xiàn)線程同步的
    2) 不是說有多線程就需要加鎖
image
j) @synchronized
    1) @synchronized是對(duì)mutex遞歸鎖的封裝
    2) 源碼查看:objc4中的objc-sync.mm文件
    3) @synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的遞歸鎖日戈,然后進(jìn)行加鎖、解鎖操作
    4) 性能比較差,蘋果官方不推薦使用,所以代碼提示也沒有
image
  • 9.iOS線程同步方案性能比較
    image
  • 10.自旋鎖孙乖、互斥鎖比較
a) 什么情況使用自旋鎖比較劃算浙炼?
    1) 預(yù)計(jì)線程等待鎖的時(shí)間很短
    2) 加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用份氧,但競(jìng)爭(zhēng)情況很少發(fā)生
    3) CPU資源不緊張
    4) 多核處理器

b) 什么情況使用互斥鎖比較劃算?
    1) 預(yù)計(jì)線程等待鎖的時(shí)間較長(zhǎng)
    2) 臨界區(qū)有IO操作
    3) 臨界區(qū)代碼復(fù)雜或者循環(huán)量大
    4) 臨界區(qū)競(jìng)爭(zhēng)非常激烈
    5) 單核處理器
    
c) 臨界區(qū):lock與unlock之間的代碼 

d) IO操作:文件操作(讀和寫的操作)
  • 11.atomic
a) atomic用于保證屬性setter弯屈、getter的原子性操作蜗帜,相當(dāng)于在getter和setter內(nèi)部加了線程同步的鎖

b) 可以參考源碼objc4的objc-accessors.mm

c) 它并不能保證使用屬性的過程是線程安全的
  • 12.iOS中的讀寫安全方案
a) 思考如何實(shí)現(xiàn)以下場(chǎng)景
    1) 同一時(shí)間,只能有1個(gè)線程進(jìn)行寫的操作
    2) 同一時(shí)間资厉,允許有多個(gè)線程進(jìn)行讀的操作
    3) 同一時(shí)間厅缺,不允許既有寫的操作,又有讀的操作

b) 上面的場(chǎng)景就是典型的“多讀單寫”宴偿,經(jīng)常用于文件等數(shù)據(jù)的讀寫操作

c) iOS中的實(shí)現(xiàn)方案有
    1) pthread_rwlock:讀寫鎖
image
    2) dispatch_barrier_async:異步柵欄調(diào)用
        2.1) 這個(gè)函數(shù)傳入的并發(fā)隊(duì)列必須是自己通過dispatch_queue_cretate創(chuàng)建的
        2.2) 如果傳入的是一個(gè)串行或是一個(gè)全局的并發(fā)隊(duì)列湘捎,那這個(gè)函數(shù)便等同于dispatch_async函數(shù)的效果
image
  • 13.GNUstep
a) GNUstep是GNU計(jì)劃的項(xiàng)目之一,它將Cocoa的OC庫重新開源實(shí)現(xiàn)了一遍

b) 源碼地址:http://www.gnustep.org/resources/downloads.php

c) 雖然GNUstep不是蘋果官方源碼窄刘,但還是具有一定的參考價(jià)值
  • 14.其它知識(shí)點(diǎn)總結(jié)
a) lldb查看匯編指令級(jí)別代碼時(shí)一行一行的運(yùn)行 
    1) stepi(si)
    2) nexti(ni):也是一行一行,但是遇到函數(shù)調(diào)用會(huì)一筆帶過這個(gè)函數(shù)調(diào)用
    3) c:直接跳到下一個(gè)斷點(diǎn)
    
b) 定義變量的時(shí)候同時(shí)給他賦值結(jié)構(gòu)體可以這么干窥妇,但是不能直接給結(jié)構(gòu)體賦值

c) 線程的任務(wù)一旦執(zhí)行完畢,生命周期就結(jié)束了都哭,無法再使用 // 準(zhǔn)確來講秩伞,使用runloop是為了讓線程保持激活狀態(tài)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市欺矫,隨后出現(xiàn)的幾起案子纱新,更是在濱河造成了極大的恐慌,老刑警劉巖穆趴,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脸爱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡未妹,警方通過查閱死者的電腦和手機(jī)簿废,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來络它,“玉大人族檬,你說我怎么就攤上這事』粒” “怎么了单料?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)点楼。 經(jīng)常有香客問我扫尖,道長(zhǎng),這世上最難降的妖魔是什么掠廓? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任换怖,我火速辦了婚禮,結(jié)果婚禮上蟀瞧,老公的妹妹穿的比我還像新娘沉颂。我一直安慰自己条摸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布兆览。 她就那樣靜靜地躺著屈溉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抬探。 梳的紋絲不亂的頭發(fā)上子巾,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音小压,去河邊找鬼线梗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛怠益,可吹牛的內(nèi)容都是我干的仪搔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蜻牢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼烤咧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抢呆,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤煮嫌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后抱虐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昌阿,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年恳邀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了懦冰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谣沸,死狀恐怖刷钢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乳附,我是刑警寧澤闯捎,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站许溅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秉版。R本人自食惡果不足惜贤重,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望清焕。 院中可真熱鬧并蝗,春花似錦祭犯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至键畴,卻和暖如春最盅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背起惕。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工涡贱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惹想。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓问词,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親嘀粱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子激挪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • 身為開發(fā)者的我們,總是會(huì)面臨著各種各樣的需求.必不可少的一個(gè)硬性規(guī)則:從用戶體驗(yàn)的角度來開發(fā)項(xiàng)目!那么這就要求我...
    Small_Potato閱讀 451評(píng)論 2 8
  • 進(jìn)程 1.進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序2.每個(gè)進(jìn)程之間是相互獨(dú)立的,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存...
    hmj1993閱讀 1,717評(píng)論 1 3
  • GCD是Grand Central Dispatch的縮寫锋叨,有人叫它大中樞派發(fā)垄分、或者大中央調(diào)度,不管叫啥悲柱,總之锋喜,它...
    xfs_coder閱讀 461評(píng)論 0 1
  • 一、進(jìn)程與線程 1.進(jìn)程: 系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序豌鸡,每個(gè)進(jìn)程之間是獨(dú)立的嘿般,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)...
    云上的彩閱讀 671評(píng)論 0 0
  • 一蛇更、多線程N(yùn)SThread 1.多線程基礎(chǔ)知識(shí) 線程與進(jìn)程的關(guān)系(1). 線程是CPU執(zhí)行任務(wù)的基本單位瞻赶,一個(gè)進(jìn)程...
    IOS_龍閱讀 586評(píng)論 0 8