前言
最近想系統的研究下iOS上的多線程,就搜集了大量的資料,在這些資料的基礎之上形成了這篇文章。一方面希望自己加深下印象,另外一方面也希望對他人提供一些幫助。由于本人水平有限,難免出現錯誤和疏漏之處,還請讀者見諒。本篇文章主要參考了李明杰老師的教程和一些優秀的文章,再此深表感謝。
1、基本概念
-
進程
進程是指在系統中正在運行的一個應用程序。例如,同時打開QQ和Xcode,系統就會分別啟動2個進程。在MAC電腦上,可以通過活動監視器查看進程。
活動監視器.png 線程
一個進程想要執行任務,必須得有線程(每1個進程至少要有1條線程)。線程是進程的基本執行單元,一個進程(程序)的所有任務都在線程中執行。例如,使用網易云音樂播放音樂、使用迅雷下載電影等都需要在線程中進行。主線程
處理UI,所有更新UI的操作都必須在主線程上執行。不要把耗時操作放在主線程,會卡界面。線程的串行
一個線程中的任務的執行是串行的。如果要在1個線程中執行多個任務,那么只能一個一個地按順序執行這些任務。也就是說,在同一時間內,1個線程只能執行1個任務。多線程
一個進程中可以開啟多條線程,每條線程可以并行(同時)執行不同的任務。進程類似于實際生活中的車間,而線程可以理解為車間中的工人。
2、線程的狀態與生命周期
下圖是線程狀態示意圖,從圖中可以看出線程的生命周期是:新建-就緒-運行-阻塞-死亡
下面分別闡述線程生命周期中的每一步
- 新建:實例化線程對象
- 就緒:向線程對象發送start消息,線程對象被加入可調度線程池等待CPU調度。
- 運行:CPU負責調度可調度線程池中線程的執行。線程執行完成之前,狀態可能會在就緒和運行之間來回切換。就緒和運行之間的狀態變化由CPU負責,程序員不能干預。
- 阻塞:當滿足某個預定條件時,可以使用休眠或鎖,阻塞線程執行。sleepForTimeInterval(休眠指定時長),sleepUntilDate(休眠到指定日期),@synthesized(self):(互斥鎖)
- 死亡:正常死亡,線程執行完畢。非正常死亡,當滿足某個條件后,在線程內部中止執行/在主線程中止線程對象。
- 線程的exit和cancel:
[NSThread exit]:一旦強行終止線程,后續的所有代碼都不會被執行。
[thread cancek]:并不會直接取消線程,只是給線程對象添加isCancelled標記。
3、多線程的原理
在同一時間內,(單核)CPU只能處理1條線程,只有1條線程在工作(執行)。因此,多線程并發(同時)執行,其實是CPU快速地在多條線程之間調度(切換)。如果CPU調度線程的時間足夠快,就造成了多線程并發執行的假象。
思考:如果線程非常非常多,會發生什么情況?
1、CPU會在N多線程之間調度,CPU會累死,消耗大量的CPU資源
2、每條線程被調度執行的頻次會降低(線程的執行效率降低)
4、多線程的優缺點
多線程的優點
1、能適當提高程序的執行效率
2、能適當提高資源利用率(CPU、內存利用率)多線程的缺點
1、開啟線程需要占用一定的內存空間(默認情況下,主線程占用1M,子線程占用512KB),如果開啟大量的線程,會占用大量的內存,降低程序的性能
2、線程越多,CPU在調度線程上的開銷就越大
3、程序設計會更加復雜(比如線程之間的通信、多線程的數據共享)
5、多線程在iOS開發中的應用
什么是主線程
一個iOS程序運行后,默認會開啟1條線程,稱之為“主線程”或“UI線程”主線程的主要作用
1、顯示/刷新UI界面
2、處理UI事件(比如點擊事件、滾動事件、拖拽事件等)主線程的使用注意
1、不要將比較耗時的操作放到主線程中,因為耗時操作會卡住主線程,嚴重影響UI的流暢度,給用戶一種“卡”的壞體驗。
2、將耗時操作放在子線程(后臺線程、非主線程)中執行
6、多線程的四種解決方案
多線程的四種解決方案分別是:pthread,NSThread,GCD,NSOperation。
下圖給出了這四種方案的解讀和對比。
7、線程安全問題
當多個線程訪問同一塊資源時,很容易引發數據錯亂和數據安全問題。就好比幾個人在同一時修改同一個表格,造成數據的錯亂。
解決多線程安全問題的方法
- 方法一:互斥鎖(同步鎖)
@synchronized(鎖對象) {
// 需要鎖定的代碼
}
判斷的時候鎖對象要存在,如果代碼中只有一個地方需要加鎖,大多都使用self作為鎖對象么這樣可以避免單獨再創建一個鎖對象。
加了互斥鎖的代碼,當新的線程訪問時,如果發現其他線程正在執行鎖定的代碼,新線程就會進入休眠。
- 方法二:自旋鎖
加了自旋鎖,當新線程訪問代碼時,如果發現有其他線程正在鎖定代碼,新線程就會用死循環的方式,一直等待鎖定的代碼執行完成。相當于不停嘗試執行代碼,比較消耗性能。
屬性修飾atomic本身就有一把自旋鎖。
下面說明了屬性修飾nonatomic和atomic
nonatomic 非原子屬性,同一時間可以有很多線程讀和寫
atomic 原子屬性(線程安全),保證同一時間只有一個線程能夠寫入(但是同一個時間多個線程都可以取值),atomic 本身就有一把鎖(自旋鎖)
atomic:線程安全,需要消耗大量的資源
nonatomic:非線程安全,不過效率更高,一般使用nonatomic
8、小結
本節主要介紹了多線程的基礎知識,從下節開始介紹iOS多線程的具體使用。
相關系列文章
iOS多線程詳解(一)--- 多線程基礎
iOS多線程詳解(二)--- pthread&NSThread
iOS多線程詳解(三)--- GCD
iOS多線程詳解(四)--- NSOperation
iOS多線程詳解(五)--- 線程安全(鎖的創建)
iOS多線程詳解(六)--- 線程安全(Property)
參考資料:
1、李明杰老師的iOS視頻教程
2、http://www.cocoachina.com/ios/20170707/19769.html