iOS多線程原理

多線程原理

線程和進程的關(guān)系和區(qū)別

1、線程定義

  • 線程是進程的基本執(zhí)行單元,一個進程的所有任務(wù)都要在線程中執(zhí)行
  • 進程要想執(zhí)行任務(wù),必須得有線程,進程至少要有一條線程
  • 程序啟動默認會創(chuàng)建一條線程,這條線程被稱為主線程或者UI線程

2、進程定義

  • 進程是指在系統(tǒng)中正在運行的一個應(yīng)用程序
  • 每個進程之間是獨立的,每個進程運行在其專用的受保護的內(nèi)存中

3、進程和線程的區(qū)別

  • 地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間
  • 資源擁有:同一進程內(nèi)的線程共享本進程的資源,如內(nèi)存、I/O、CPU等,但是進程之間的資源是獨立的。
  • 可靠性:一個進程崩潰后,在保護模式下不會對其他進程產(chǎn)生影響,而一個線程崩潰整個進程都得死掉。所以多進程要比多線程健壯。
  • 進程切換時,消耗的資源大,效率低。所以涉及到頻繁的切換時,使用線程要好于進程。同樣如果要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程不能用進程
  • 執(zhí)行過程:每個獨立的進程有一個程序運行的入口和順序執(zhí)行序列。但是線程不能獨立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。
  • 線程是處理器調(diào)度的基本單位,但是進程不是。
對比維度 多進程 多線程 總結(jié)
數(shù)據(jù)共享、同步 數(shù)據(jù)共享復(fù)雜,需要用IPC;數(shù)據(jù)是分開的,同步簡單 因為共享進程數(shù)據(jù),數(shù)據(jù)共享簡單,但也是因為這個原因?qū)е峦綇?fù)雜 各有優(yōu)勢
內(nèi)存、CPU 占用內(nèi)存多,切換復(fù)雜,CPU利用率低 占用內(nèi)存少,切換簡單,CPU利用率高 線程占優(yōu)
創(chuàng)建銷毀、切換 創(chuàng)建銷毀、切換復(fù)雜,速度慢 創(chuàng)建銷毀、切換簡單,速度很快 線程占優(yōu)
編程、調(diào)試 編程簡單,調(diào)試簡單 編程復(fù)雜,調(diào)試復(fù)雜 進程占優(yōu)
可靠性 進程間不會互相影響 一個線程掛掉將導(dǎo)致整個進程掛掉 進程占優(yōu)
分布式 適應(yīng)于多核、多機分布式;如果一臺機器不夠,擴展到多臺機器比較簡單 適應(yīng)于多核分布式 進程占優(yōu)

多線程的意義

  • 優(yōu)點
    • 能適當(dāng)提高程序的執(zhí)行效率
    • 能適當(dāng)提高資源的利用率
    • 線程上的任務(wù)執(zhí)行完成后,線程會自動銷毀
  • 缺點
    • 開啟線程需要占用一定的內(nèi)存空間(默認一個線程大小為512KB)
    • 如果開啟大量的線程,會占用大量的內(nèi)存空間,降低程序的性能
    • 線程越多,CPU在調(diào)用線程上的開銷就越大
    • 程序設(shè)計更加復(fù)雜,比如線程間的通信、多線程的數(shù)據(jù)共享

多線程的原理

CPU在不同的線程之間以一個非常小的時間片不斷的進行調(diào)度。

多線程技術(shù)方案

1、pthread

  • 一套通用的多線程API
  • 適用于Unix/Linux/Windows等系統(tǒng)
  • 跨平臺/可移植
  • 使用難度大
  • C語言,需要手動管理線程生命周期

2、NSThread

  • 使用更加面向?qū)ο?/li>
  • 簡單易用,可直接操作線程對象
  • OC語言,需要手動管理線程對象

3、GCD

  • 蘋果為多核并行運算開發(fā)的解決方案
  • 會自動利用更多的CPU內(nèi)核(比如雙核、四核)
  • 程序員只需要將任務(wù)添加到隊列中,不需要編寫任何線程管理代碼
  • OC語言,自動管理生命周期

4、NSOperation

  • 基于GCD,但是比GCD多了一些簡單實用的功能
  • 使用更加面向?qū)ο?/li>
  • 可添加完成的代碼塊,在操作完成之后執(zhí)行
  • 添加操作之間的依賴關(guān)系,方便的控制執(zhí)行順序
  • 可以設(shè)定操作執(zhí)行的優(yōu)先級
  • 可以很方便的取消一個操作的執(zhí)行
  • 使用KVO觀察對操作執(zhí)行狀態(tài)的更改:isExecuteing、isFinished、isCancelled
  • OC語言,手動管理生命周期

C與OC的橋接

  • __bridge只做類型轉(zhuǎn)換,但是不修改對象(內(nèi)存)管理權(quán);
  • __bridge_retained(也可以使用CFBridgingRetain)將Objective-C的對象轉(zhuǎn)換為Core Foundation的對象,同時將對象(內(nèi)存)的管理權(quán)交給Core Foundation的對象,后續(xù)使用CFRelease或者相關(guān)方法來釋放對象;
  • __bridge_transfer(也可以使用CFBridgingRelease)將Core Foundation的對象轉(zhuǎn)換為Objective-C的對象,同時將對象(內(nèi)存)的管理權(quán)交給ARC。

線程生命周期

線程的生命周期分為5個部分,新建、就緒、運行、阻塞、死亡。

線程生命周期.png

  • 新建:實例化線程對象
  • 就緒:向線程對象發(fā)送start消息,線程對象被加入可調(diào)度線程池等待CPU調(diào)度
  • 運行:CPU負責(zé)調(diào)度可調(diào)度線程池中線程執(zhí)行。當(dāng)前線程任務(wù)執(zhí)行完畢后,進入就緒狀態(tài),即有一個短暫停留期,如果在這期間有新的任務(wù),則繼續(xù)執(zhí)行這個任務(wù),如果沒有新的任務(wù),則線程銷毀,等有下一個任務(wù)的時候,則開啟新的線程執(zhí)行。
  • 阻塞:當(dāng)滿足某個預(yù)定條件時,可以使用休眠或鎖,阻塞線程執(zhí)行。sleepForTimeInterval(休眠指定時長),sleepUntilDate(休眠到指定日期),@synchronized(self):(互斥鎖)。
  • 死亡:正常死亡,線程執(zhí)行完畢。非正常死亡,當(dāng)滿足某個條件后,在線程內(nèi)部中止執(zhí)行或者在主線程中止線程對象。

線程的exit、cancel和suspend操作區(qū)別。

  • exit:一旦強行終止線程,后續(xù)的所有代碼都不會被執(zhí)行
  • cancel:并不會直接取消線程,只是給線程對象添加isCancelled標(biāo)記
  • suspend:掛起狀態(tài),通過resume,可以恢復(fù)線程的任務(wù)執(zhí)行
線程聲明周期2

線程池的實現(xiàn)原理

線程池的實現(xiàn)原理如下圖所示:


線程池實現(xiàn)原理.png

線程安全與鎖

1、什么是線程安全?
????多線程操作共享數(shù)據(jù)不會出現(xiàn)想不到的結(jié)果就是線程安全的,否則,是線程不安全的。比如:多個線程同時訪問或讀取同一共享數(shù)據(jù),每個線程的讀到的數(shù)據(jù)都是一樣的,也就不存在線程不安全。如果多個線程對同一資源進行讀寫操作,那么每個線程讀到的結(jié)果就是不可預(yù)料的,線程是不安全的。

2、多線程鎖
????線程安全的解決方法就是加鎖 。
????鎖是最常用的同步工具。一段代碼段在同一個時間只能允許被一個線程訪問。
????不要將過多的其他操作代碼放到里面,否則一個線程執(zhí)行的時候另一個線程就一直在等待,就無法發(fā)揮多線程的作用了。下圖是iOS常用鎖的性能表。

鎖的性能對比.png

具體各種鎖的介紹看文章:
1、iOS多線程-各種線程鎖的簡單介紹
2、iOS開發(fā)中的11種鎖整理

3、atomic與nonatomic的區(qū)別

  • nonatomic 非原子屬性
  • atomic 原子屬性(線程安全),針對多線程設(shè)計,默認值
    • 保證同一時間只有一個線程能夠?qū)懭耄ǖ峭粫r間多個線程都可取值)
    • atomic本身就有一把鎖(自旋鎖)
    • 單寫多讀:單個線程寫入,多個線程可以讀取
  • atomic:并非完全的線程安全,只有用setter方法寫入才是線程安全的,需要消耗大量資源
  • nonatomic:非線程安全,適合內(nèi)存小的移動設(shè)備、

建議:

  • 所有屬性都聲明為nonatomic
  • 盡量避免多線程搶奪同一塊資源
  • 盡量將加鎖、資源搶奪的業(yè)務(wù)邏輯交給服務(wù)器端處理,減小移動客戶端的壓力

線程和runloop的關(guān)系

1、runloop與線程是一一對應(yīng)的,一個runloop對應(yīng)一個核心的線程,為什么說是核心的,是因為runloop是可以嵌套的,但是核心的只能有一個,他們的關(guān)系保存在一個全局的字典里。

2、runloop是來管理線程的,當(dāng)線程的runloop被開啟后,線程會在執(zhí)行完任務(wù)后進入休眠狀態(tài),有了任務(wù)就會被喚醒去執(zhí)行任務(wù)。

3、runloop在第一次獲取時被創(chuàng)建,在線程結(jié)束時被銷毀。

4、對于主線程來說,runloop在程序一啟動就默認創(chuàng)建好了。

5、對于子線程來說,runloop是懶加載的,只有當(dāng)我們使用的時候才會去創(chuàng)建,所以在子線程用定時器要注意:確保子線程的runloop被創(chuàng)建,不然定時器不會回調(diào)。

參考文章:
1、淺談多進程多線程的選擇
2、多線程原理分析
3、iOS多線程全套:線程生命周期,多線程的四種解決方案,線程安全問題,GCD的使用,NSOperation的使用
4、iOS線程通信和進程通信的例子(NSMachPort和NSTask,NSPipe)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,689評論 1 32
  • iOS多線程編程 基本知識 1. 進程(process) 進程是指在系統(tǒng)中正在運行的一個應(yīng)用程序,就是一段程序的執(zhí)...
    陵無山閱讀 6,364評論 1 14
  • Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時執(zhí)行代碼、方法又是什么? 1...
    AlanGe閱讀 1,929評論 0 17
  • 進程和線程 進程 所有運行中的任務(wù)通常對應(yīng)一個進程,當(dāng)一個程序進入內(nèi)存運行時,即變成一個進程.進程是處于運行過程中...
    勝浩_ae28閱讀 5,261評論 0 23
  • 又來到了一個老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個問題開始,來談?wù)劜?..
    tangsl閱讀 4,332評論 0 23

友情鏈接更多精彩內(nèi)容