多線程
標籤(空格分隔): 網絡多線程
基礎概念
進程
- 進程是指在系統中正在運行的一個應用程序
- 每個進程之間是獨立的,每個進程均運行在其專用且受保護的內存空間內
- 例如當我們打開微信的時候系統就會開啓一個進程
線程
- 1個進程要想執行任務,必須得有線程(每1個進程至少要有1條線程)
- 一個進程(程序)的所有任務都在線程中執行(當我們使用酷我播放音樂,打開迅雷下載資源,這些都是在線程中執行的)
線程的串行
- 個線程中任務的執行是串行的
- 如果要在1個線程中執行多個任務,那麼只能一個一個地按順序執行這些任務
- 也就是說,在同一時間內,1個線程只能執行1個任務
多線程
- 1個進程中可以開啓多條線程,多條線程可以並行(同時)執行不同的任務
多線程技術可以提高程序的執行效率(比如迅雷同時下載幾個文件)
實現原理:
- 同一時間,CPU只能處理1條線程,只有1條線程在工作(執行),多線程併發(同時)執行,其實是CPU快速地在多條線程之間調度(切換),如果CPU調度線程的時間足夠快,就造成了多線程併發執行的假象
- 所以線程不能太多,不然cpu的頻繁切換大量消耗了cpu的資源,線程的執行效率就會變低
- 優點:能適當提高程序的執行效率,能適當提高資源利用率(CPU、內存利用率)
- 缺點:
- 創建線程是有開銷的,iOS下主要成本包括:內核數據結構(大約1KB)、棧空間(子線程512KB、主線程1MB,也可以使用-setStackSize:設置,但必須是4K的倍數,而且最小是16K),創建線程大約需要90毫秒的創建時間
- 如果開啓大量的線程,會降低程序的性能
- 線程越多,CPU在調度線程上的開銷就越大
- 程序設計更加複雜:比如線程之間的通信、多線程的數據共享
多線程在iOS開發中的應用
主線程
- 一個iOS程序運行後,默認會開啓1條線程,稱爲“主線程”或“UI線程”
- 主線程的作用
- 顯示\刷新UI界面
- 處理UI事件(比如點擊事件、滾動事件、拖拽事件等
- 主線程的使用注意
- 別將比較耗時的操作放到主線程中
- 耗時操作會卡住主線程,嚴重影響UI的流暢度,給用戶一種“卡”的壞體驗
NSThread
- 一個NSThread對象就代表一條線程
- 創建、啓動線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
- 獲取當前線程
NSThread *current = [NSThread currentThread];
- 線程的名字
- (void)setName:(NSString *)n;
其他創建線程方式
創建線程後自動啓動線程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
隱式創建並啓動線程
[self performSelectorInBackground:@selector(run) withObject:nil];
線程狀態
- 線程狀態:
- (void)start;
// 進入就緒狀態 -> 運行狀態。當線程任務執行完畢,自動進入死亡狀態
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 進入阻塞狀態
+ (void)exit;
強制停止線程
// 進入死亡狀態
多線程安全隱患
資源共享
1塊資源可能會被多個線程共
- 比如多個線程訪問同一個對象、同一個變享,也就是多個線程可能會訪問同一塊資源量、同一個文件
當多個線程訪問同一塊資源時,很容易引發數據錯亂和數據安全問題
安全隱患解決 – 互斥鎖
互斥鎖使用格式:
@synchronized(鎖對象) { // 需要鎖定的代碼 }
注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的互斥鎖的優缺點
- 優點:能有效防止因多線程搶奪資源造成的數據安全問題
- 缺點:需要消耗大量的CPU資源
互斥鎖的使用前提:多條線程搶奪同一塊資源
線程同步的意思是:多條線程在同一條線上執行(按順序地執行任務)
- 互斥鎖,就是使用了線程同步技術(線程同步的意思是:多條線程在同一條線上按順序地執行任務)
原子和非原子屬性
- OC在定義屬性時有nonatomic和atomic兩種選擇
atomic:原子屬性,爲setter方法加鎖(默認就是atomic)
nonatomic:非原子屬性,不會爲setter方法加鎖
nonatomic和atomic對比
- atomic:線程安全,需要消耗大量的資源
- nonatomic:非線程安全,適合內存小的移動設備
iOS開發的建議:
- 所有屬性都聲明爲nonatomic
- 儘量避免多線程搶奪同一塊資源
- 儘量將加鎖、資源搶奪的業務邏輯交給服務器端處理,減小移動客戶端的壓力
- 注意點:
- atomic系統自動給我們添加的鎖不是互斥鎖其實是自旋鎖
- 互斥鎖和自旋鎖共同點
- 都能夠保證多線程在同一時候, 只能有一個線程操作鎖定的代碼
- 互斥鎖和自旋鎖不同點
- 如果是互斥鎖, 假如現在被鎖住了,那麼後面來得線程就會進入”休眠”狀態, 直到解鎖之後, 又會喚醒線程繼續執行
- 如果是自旋鎖, 假如現在被鎖住了, 那麼後面來得線程不會進入休眠狀態, 會一直傻傻的等待, 直到解鎖之後立刻執行
- 自旋鎖更適合做一些較短的操作
線程間的通信
在1個進程中,線程往往不是孤立存在的,多個線程之間需要經常進行通信
線程間通信的體現
- 1個線程傳遞數據給另1個線程
- 在1個線程中執行完特定任務後,轉到另1個線程繼續執行任務
線程間通信常用方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;