2020-11-12 iOS開發(fā)多線程

多線程

進(jìn)程:
1,是一個具有一定獨(dú)立功能的程序箫章,操作系統(tǒng)分配資源的基本單位
2,在系統(tǒng)中正在運(yùn)行的一個應(yīng)用程序怕午,就是一段程序執(zhí)行過程,我們可以理解為手機(jī)上的一個app
3橘原,每個進(jìn)程之間是獨(dú)立的,每個進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi)涡上,擁有獨(dú)立運(yùn)行所需的全部資源

線程:
1趾断,程序執(zhí)行流的最小單位,線程是進(jìn)程中的一個實體
2吓懈,一個進(jìn)程要想執(zhí)行任務(wù)歼冰,必須至少要有一條線程靡狞,應(yīng)用程序啟動的時候系統(tǒng)會默認(rèn)開啟一跳線程耻警,這就是主線程

進(jìn)程和線程的關(guān)系

1,線程是進(jìn)程的執(zhí)行單元甸怕,進(jìn)程的所有任務(wù)都在線程中執(zhí)行
2甘穿,線程是cpu分配資源和調(diào)度的最小單位
3,一個程序可以對應(yīng)多個進(jìn)程梢杭,一個進(jìn)程可以有多個線程温兼,但至少要有一個線程
4,同一個進(jìn)程內(nèi)的線程共享進(jìn)程資源

多進(jìn)程武契,多線程

1募判,進(jìn)程是程序在計算機(jī)上的一個執(zhí)行活動,當(dāng)你運(yùn)行一個程序咒唆,你就啟動了一個進(jìn)程届垫,顯然程序是死的(靜態(tài)的),進(jìn)程是活的(動態(tài)的)
2全释,進(jìn)程分為系統(tǒng)進(jìn)程和用戶進(jìn)程装处,用于完成操作系統(tǒng)的各種功能的進(jìn)程是系統(tǒng)進(jìn)程,所有由用戶啟動的進(jìn)程都是用戶進(jìn)程浸船,進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的單位
3妄迁,進(jìn)程又被細(xì)化為線程寝蹈,也就是一個進(jìn)程下有多個能獨(dú)立運(yùn)行的更小單位,在同一個時間同一個計算機(jī)系統(tǒng)中如果允許兩個或兩個以上的進(jìn)程出于運(yùn)行狀態(tài)登淘,這便是多線程箫老。

1,同一時間形帮,cpu只能處理一條線程槽惫,只有1條線程在執(zhí)行。多線程并發(fā)執(zhí)行辩撑,其實是cpu快速的在多條線程之間調(diào)度(切換)界斜,如果cpu調(diào)度線程的時間足夠快,就能造成多線程并發(fā)執(zhí)行的假象
2合冀,如果線程非常非常多各薇,cpu會在N多線程之間調(diào)度,消耗大量的cpu資源君躺,每條線程被調(diào)度執(zhí)行的頻次會降低(線程的執(zhí)行效率降低)
3峭判,優(yōu)點:能適當(dāng)提高程序的執(zhí)行效率,能適當(dāng)提高資源利用率
4棕叫,缺點:開啟線程會占用一定的內(nèi)存(主線程1m 子線程512kb)林螃,如果開啟大量的線程,會占用大量的內(nèi)存空間俺泣,降低程序的性能疗认,線程越多,cpu在調(diào)度線程上的開銷就越大伏钠,程序設(shè)計的更加復(fù)雜:比如線程之間的通信横漏,多線程的數(shù)據(jù)共享

任務(wù)、隊列

任務(wù):就是執(zhí)行操作的意思熟掂,執(zhí)行任務(wù)的方式有兩種:同步執(zhí)行(sync)和異步執(zhí)行(async)
同步:同步添加任務(wù)到指定的隊列中缎浇,在添加的任務(wù)執(zhí)行結(jié)束之前,會一直等待赴肚,知道隊列里面的任務(wù)完成之后再繼續(xù)執(zhí)行素跺,即會阻塞線程,只能在當(dāng)前線程中執(zhí)行任務(wù)(是當(dāng)前線程誉券,不一定是主線程)指厌,不具備開啟新線程的能力
異步:線程會立即返回,無需等待就會繼續(xù)執(zhí)行下面的任務(wù)横朋,不阻塞當(dāng)前線程仑乌,可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力(并不一定開啟新線程),如果不是添加到主隊列上晰甚,異步會在子線程中執(zhí)行任務(wù)

隊列

這里的隊列指執(zhí)行任務(wù)的等待隊列衙传,用來存放任務(wù)的隊列,隊列是一種特殊的線性標(biāo)厕九,采用先進(jìn)先出的原則蓖捶,新任務(wù)總是被插入到隊列的末尾,而讀取任務(wù)的時候總是從隊列的頭部開始讀取扁远,每讀取一個任務(wù)俊鱼,則從隊列中釋放一個任務(wù)
在GCD中有兩種隊列,串行隊列和并發(fā)隊列畅买,兩者都符合先進(jìn)先出的原則并闲,兩者的主要區(qū)別是執(zhí)行順序不同,以及開啟線程數(shù)不同谷羞。

串行隊列:同一時間帝火,隊列中只能執(zhí)行一個任務(wù),只有當(dāng)前的任務(wù)執(zhí)行完成之后湃缎,才能執(zhí)行下一個任務(wù)犀填,主隊列是主線程上的一個串行隊列,是系統(tǒng)自動為我們創(chuàng)建的
并發(fā)隊列:同時允許多個任務(wù)并發(fā)執(zhí)行嗓违,并發(fā)隊列的并發(fā)功能只有在異步函數(shù)下才有效

iOS中的多線程

主要有三種:NSThread九巡、NSoperationQueue、GCD

NSThread:輕量級別的多線程技術(shù)
是我們自己手動開辟的子線程蹂季,如果使用的是初始化方式就需要我們自己啟動冕广,如果使用的是構(gòu)造器方式他就會自動啟動,只要是我們手動開辟的線程乏盐,都需要我們自己管理該線程佳窑,不只是啟動制恍,還有該線程使用完畢后的資源回收


image.png

GCD對比NSOprationQueue
1父能,gcd執(zhí)行效率更高,而且由于隊列中執(zhí)行的是block構(gòu)成的任務(wù)净神,這是一個輕量級的數(shù)據(jù)結(jié)構(gòu)何吝,寫起來方便
2,gcd只支持先進(jìn)先出FIFO的隊列鹃唯,而且NSOperationQueue可以通過設(shè)置最大并發(fā)數(shù)爱榕,設(shè)置優(yōu)先級,添加依賴關(guān)系等調(diào)整執(zhí)行順序
3坡慌,NSOperationQueue甚至可以跨隊列設(shè)置依賴關(guān)系黔酥,但是gcd只能通過設(shè)置串行隊列,或者在隊列內(nèi)添加barrier任務(wù),才能控制執(zhí)行順序跪者,較為復(fù)雜
4棵帽,NSOperationQueue面向?qū)ο螅灾С諯VO渣玲,可以監(jiān)測operation是否正在執(zhí)行 是否結(jié)束 是否取消
(十幾開發(fā)中很多只會用到異步操作逗概,不會有特別復(fù)雜的線程關(guān)系管理,所以蘋果推薦優(yōu)化完善忘衍,運(yùn)行快速的gcd是首選 如果考慮異步操作之間的事務(wù)性逾苫,順序性,依賴關(guān)系枚钓,gcd需要自己寫很多的代碼來實現(xiàn)铅搓,而NSOperationQueue已經(jīng)內(nèi)建了這些支持,NSThread需要我們自己去管理線程的生命周期搀捷,還要考慮線程同步狸吞,加鎖問題,造成一些性能上的開銷)

GCD

GCD共有三種隊列類型

main queue:通過dispatch-get-main-queue()獲得指煎,這是一個與主線程相關(guān)的串行隊列
global queue:全局隊列是并發(fā)隊列蹋偏,由整個進(jìn)程共享,存在高中低三種優(yōu)先級的全局隊列至壤,調(diào)用dispath-get-global-queue并傳入優(yōu)先級來訪問隊列
自定義隊列:通過函數(shù)dispatch-queue-create創(chuàng)建的隊列

死鎖

死鎖就是隊列引起的循環(huán)等待
一個比較常見的死鎖例子:主隊列同步


image.png

同樣下面的代碼也會造成死鎖:


image.png

外面的函數(shù)無論是同步還是異步都會造成死鎖
這是因為里面的任務(wù)和外面的任務(wù)都在同一個隊列內(nèi)
又是同步威始,這就和上邊主隊列同步的例子一樣造成了死鎖
解決方法也和上邊一樣,將里面的同步改成異步或者將隊列換成串行或并行

GCD任務(wù)執(zhí)行順序

串行隊列先異步后同步


image.png

打印順序: 13245
原因是: 首先先打印 1 接下來將任務(wù) 2 其添加至串行隊列上像街,由于任務(wù) 2 是異步黎棠,不會阻塞線程,繼續(xù)向下執(zhí)行镰绎,打印 3 然后是任務(wù) 4,將任務(wù) 4 添加至串行隊列上脓斩,因為任務(wù) 4 和任務(wù) 2 在同一串行隊列,根據(jù)隊列先進(jìn)先出原則畴栖, 任務(wù) 4 必須等任務(wù) 2 執(zhí)行后才能執(zhí)行随静,又因為任務(wù) 4 是同步任務(wù),會阻塞線程吗讶,只有執(zhí)行完任務(wù) 4 才能繼 續(xù)向下執(zhí)行打印 5 所以最終順序就是 13245燎猛。 這里的任務(wù) 4 在主線程中執(zhí)行,而任務(wù) 2 在子線程中執(zhí)行照皆。 如果任務(wù) 4 是添加到另一個串行隊列或者并行隊列重绷,則任務(wù) 2 和任務(wù) 4 無序執(zhí)行(可以添加多個任務(wù)看效果)

performSelector

這個方法要創(chuàng)建提交任務(wù)到runloop上的,而gcd底層創(chuàng)建的線程是默認(rèn)沒有開啟對應(yīng)runloop的膜毁,所有的這個方法就會失效
如果改為主隊列昭卓,所在的主線程是默認(rèn)開啟runloop的

延時函數(shù)

dispatch-after能讓我們添加進(jìn)隊列的任務(wù)延時執(zhí)行愤钾,該函數(shù)并不是在指定時間后執(zhí)行處理,而只是在指定時間追加處理到dispatch-queue

使用dispatch-once實現(xiàn)單例

image.png

NSOperationQueue的有點

NSOperation候醒、NSOperationQueue是蘋果提供給我們的一套多線程解決方案绰垂,十幾上他們是基于GCD更高一層的封裝,完全面對對象火焰,但是比GCD更簡單易用劲装、代碼可讀性也更高
1,可以添加任務(wù)依賴昌简,方便控制執(zhí)行順序
2占业,可以設(shè)定操作執(zhí)行的優(yōu)先級
3,任務(wù)執(zhí)行狀態(tài)控制:isready纯赎,isexecuting谦疾,isfinished,iscancelled
如果只是重寫NSOperation的main方法犬金,由底層控制變更任務(wù)執(zhí)行及完成狀態(tài)念恍,以及任務(wù)退出。
如果重寫了NSOperation的start方法晚顷,自行控制任務(wù)狀態(tài)
系統(tǒng)通過KVO的方式移除isfinished==YES的NSOperation
4峰伙,可以設(shè)置最大并發(fā)量

NSOperation 和 NSOperationQueue

操作(operation):
執(zhí)行操作的意思,換句話說就是你在線程中執(zhí)行的那段代碼
在GCD中是放在block中的该默,在NSOperation中瞳氓,使用NSOperation子類NSInvocationOperation、 NSBlockOperation栓袖,或者自定義子類來封裝操作匣摘。

操作隊列(operation queue):
這里的隊列指操作隊列,即用來存放操作的隊列裹刮。不同于 GCD 中的調(diào)度隊列 FIFO(先進(jìn)先出)的原則音榜。 NSOperationQueue 對于添加到隊列中的操作,首先進(jìn)入準(zhǔn)備就緒的狀態(tài)(就緒狀態(tài)取決于操作之間的依賴 關(guān)系)捧弃,然后進(jìn)入就緒狀態(tài)的操作的開始執(zhí)行順序(非結(jié)束執(zhí)行順序)由操作之間相對的優(yōu)先級決定(優(yōu) 先級是操作對象自身的屬性)赠叼。
操作隊列通過設(shè)置最大并發(fā)操作數(shù)(maxConcurrentOperationCount)來控制并發(fā)、串行塔橡。 NSOperationQueue 為我們提供了兩種不同類型的隊列:主隊列和自定義隊列梅割。主隊列運(yùn)行在主線程之上霜第, 而自定義隊列在后臺執(zhí)行葛家。

自旋鎖與互斥鎖

自旋鎖: 是一種用于保護(hù)多線程共享資源的鎖,與一般互斥鎖(mutex)不同之處在于當(dāng)自旋鎖嘗試獲取鎖時以忙等 待(busy waiting)的形式不斷地循環(huán)檢查鎖是否可用泌类。當(dāng)上一個線程的任務(wù)沒有執(zhí)行完畢的時候(被鎖遵恕)底燎, 那么下一個線程會一直等待(不會睡眠),當(dāng)上一個線程的任務(wù)執(zhí)行完畢弹砚,下一個線程會立即執(zhí)行双仍。 在多 CPU 的環(huán)境中,對持有鎖較短的程序來說桌吃,使用自旋鎖代替一般的互斥鎖往往能夠提高程序的性能朱沃。

互斥鎖: 當(dāng)上一個線程的任務(wù)沒有執(zhí)行完畢的時候(被鎖住)茅诱,那么下一個線程會進(jìn)入睡眠狀態(tài)等待任務(wù)執(zhí)行完畢逗物, 當(dāng)上一個線程的任務(wù)執(zhí)行完畢,下一個線程會自動喚醒然后執(zhí)行任務(wù)瑟俭。

總結(jié): 自旋鎖會忙等: 所謂忙等翎卓,即在訪問被鎖資源時,調(diào)用者線程不會休眠摆寄,而是不停循環(huán)在那里失暴,直到被鎖 資源釋放鎖。 互斥鎖會休眠: 所謂休眠微饥,即在訪問被鎖資源時逗扒,調(diào)用者線程會休眠,此時 cpu 可以調(diào)度其他線程工 作欠橘。直到被鎖資源釋放鎖缴阎。此時會喚醒休眠線程。

優(yōu)缺點:
自旋鎖的優(yōu)點在于简软,因為自旋鎖不會引起調(diào)用者睡眠蛮拔,所以不會進(jìn)行線程調(diào)度,CPU 時間片輪轉(zhuǎn)等耗時操 作痹升。所有如果能在很短的時間內(nèi)獲得鎖建炫,自旋鎖的效率遠(yuǎn)高于互斥鎖。 缺點在于疼蛾,自旋鎖一直占用 CPU肛跌,他在未獲得鎖的情況下,一直運(yùn)行--自旋察郁,所以占用著 CPU衍慎,如果不 能在很短的時 間內(nèi)獲得鎖,這無疑會使 CPU 效率降低皮钠。自旋鎖不能實現(xiàn)遞歸調(diào)用稳捆。 自旋鎖:atomic、OSSpinLock麦轰、dispatch_semaphore_t 互斥鎖:pthread_mutex乔夯、@ synchronized砖织、NSLock、NSConditionLock 末荐、NSCondition侧纯、NSRecursiveLock

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市甲脏,隨后出現(xiàn)的幾起案子眶熬,更是在濱河造成了極大的恐慌,老刑警劉巖块请,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聋涨,死亡現(xiàn)場離奇詭異,居然都是意外死亡负乡,警方通過查閱死者的電腦和手機(jī)牍白,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抖棘,“玉大人茂腥,你說我怎么就攤上這事∏惺。” “怎么了最岗?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長朝捆。 經(jīng)常有香客問我般渡,道長,這世上最難降的妖魔是什么芙盘? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任驯用,我火速辦了婚禮,結(jié)果婚禮上儒老,老公的妹妹穿的比我還像新娘蝴乔。我一直安慰自己,他們只是感情好驮樊,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布薇正。 她就那樣靜靜地躺著,像睡著了一般囚衔。 火紅的嫁衣襯著肌膚如雪挖腰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天练湿,我揣著相機(jī)與錄音猴仑,去河邊找鬼。 笑死鞠鲜,一個胖子當(dāng)著我的面吹牛宁脊,可吹牛的內(nèi)容都是我干的断国。 我是一名探鬼主播贤姆,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼榆苞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了霞捡?” 一聲冷哼從身側(cè)響起坐漏,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碧信,沒想到半個月后赊琳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砰碴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年躏筏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呈枉。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡趁尼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猖辫,到底是詐尸還是另有隱情酥泞,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布啃憎,位于F島的核電站芝囤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辛萍。R本人自食惡果不足惜悯姊,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贩毕。 院中可真熱鬧挠轴,春花似錦、人聲如沸耳幢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽睛藻。三九已至启上,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間店印,已是汗流浹背冈在。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留按摘,地道東北人包券。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓纫谅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親溅固。 傳聞我的和親對象是個殘疾皇子付秕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

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