當前位置:
首頁 > 知識 > OS X 和iOS 中的多線程技術(上)

OS X 和iOS 中的多線程技術(上)


本文梳理了OS X 和iOS 系統中提供的多線程技術。並且對這些技術的使用給出了一些實用的建議。

多線程的目的:通過並發執行提高 CPU 的使用效率,進而提供程序運行效率。

1.線程和進程進程
  • 什麼是進程

    • 進程是指在計算機系統中

      正在運行

      的一個應用程序
    • 每個進程之間是

      獨立

      的,每個進程均運行中其專用且受保護的內存空間內

  • 比如同時打開 Xcode 、Safari ,系統就會分別啟動兩個進程

OS X 和iOS 中的多線程技術(上)

  • 通過

    活動監視器

    可以查看Mac系統中所開啟的進程

線程

  • 什麼是線程
    • 一個進程要想執行任務,

      必須

      得有線程(

      每個線程至少有一條線程,即主線程

    • 一個進程的所有任務都做線程中執行
  • 比如使用酷狗播放音樂、使用迅雷下載電影,都需要在線程中執行

OS X 和iOS 中的多線程技術(上)

線程的執行方式
  • 一個線程中的任務的執行是

    串列

    • 如果要在一個線程中執行多個任務,那麼只能一個一個地按順序執行這些任務
    • 同一時間內,一個線程只能執行一個任務
  • 線程是進程中的一條執行路徑,它內部任務是

    串列

    執行的

多線程

  • 什麼是多線程
    • 一個進程中可以開啟多條線程,每條線程可以

      並行(同時)

      執行不同的任務
    • 進程好比車間,線程好比車間工人
    • 多線程技術可以提高程序的執行效率
  • 如同時開啟3條線程分別下載3個文件

OS X 和iOS 中的多線程技術(上)

  • 多線程的原理
    • 同一時間,CPU只能處理1條線程,只有1條線程在工作(執行)
    • 多線程並發(同時)執行,其實是CPU快速地在多條線程之間調度(切換)
    • 如果CPU調度線程的時間足夠快,就造成了多線程並發執行的假象

思考:如果線程非常非常多,會發生什麼情況?

CPU會在N多線程之間調度,CPU會累死,消耗大量的CPU資源
每條線程被調度執行的頻次會降低(線程的執行效率降低)

多線程的優缺點

  • 多線程的優點

    • 能適當提高程序的執行效率
    • 能適當提高資源利用率(CPU、內存利用率)
  • 多線程的缺點

    • 創建線程是有開銷的,iOS下主要成本包括:內核數據結構(大約1KB)、棧空間(子線程512KB、主線程1MB,也可以使用-setStackSize:設置,但必須是4K的倍數,而且最小是16K),創建線程大約需要90毫秒的創建時間
    • 如果開啟大量的線程,會降低程序的性能
    • 線程越多,CPU在調度線程上的開銷就越大
    • 程序設計更加複雜:比如線程之間的通信、多線程的數據共享

2 多線程在iOS開發中的應用

  • 什麼是主線程

    • 一個iOS程序運行後,默認會開啟1條線程,稱為

      「主線程」

      「UI線程」

  • 主線程的主要作用

    • 顯示刷新UI界面
    • 處理UI事件(比如點擊事件、滾動事件、拖拽事件等)
  • 主線程的使用注意

    • 別將比較耗時的操作放到主線程中
    • 耗時操作會卡住主線程,嚴重影響UI的流暢度,給用戶一種「卡」的壞體驗

iOS中多線程的實現方案

OS X 和iOS 中的多線程技術(上)

3. pthread 創建線程的簡單使用

#import // 引入對應頭文件

// 子線程調用的方法
void * run(void *param)
{
for (NSInteger i = 0; i<50000; i++) { NSLog(@"------buttonClick---%zd--%@", i, [NSThread currentThread]); } return NULL; } // 使用pthread 創建子線程並執行 - (IBAction)buttonClick:(id)sender { pthread_t thread; pthread_create(&thread, NULL, run, NULL); pthread_t thread2; pthread_create(&thread2, NULL, run, NULL); }

4 NSThread4.1 一個NSThread對象就代表一條線程

  • 創建、啟動線程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];

  • 主線程相關用法

+ (NSThread *)mainThread; // 獲得主線程
- (BOOL)isMainThread; // 是否為主線程
+ (BOOL)isMainThread; // 是否為主線程

  • 獲得當前線程

NSThread *current = [NSThread currentThread];

  • 線程的名字

- (void)setName:(NSString *)name;
- (NSString *)name;

4.2 其他創建線程的方式

  • 創建線程後自動啟動線程

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

  • 隱式創建並啟動線程

[self performSelectorInBackground:@selector(run) withObject:nil];

上述2種創建線程方式的優缺點

  • 優點:簡單快捷
  • 缺點:無法對線程進行更詳細的設置

4.3 線程的狀態

當一個線程被創建之後一共有 新建、就緒、運行、阻塞、死亡等幾種狀態。

OS X 和iOS 中的多線程技術(上)

當系統新創建一個子線程會將該線程放入到可調度線程池中,此時處於就緒狀態,當系統調度它執行任務的時候,它就處於一個運行狀態,如果該線程代用了sleep或加鎖之後,他就處於線程阻塞狀態,此時線程會被移出可調度線程池,當sleep到時或者得到同步鎖,線程又會解除阻塞狀態回到就緒狀態。當線程執行完任務之後被系統退出或者發生異常退出,就進入死亡狀態。進入死亡狀態就不能再次開啟任務

  • 啟動線程

(void)start;
// 進入就緒狀態 -> 運行狀態。當線程任務執行完畢,自動進入死亡狀態

  • 阻塞(暫停)線程

+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
+ // 進入阻塞狀態

  • 強制停止線程

+ (void)exit;
// 進入死亡狀態

5 多線程的安全隱患

  • 資源共享

    • 1塊資源可能會被多個線程共享,也就是

      多個線程可能會訪問同一塊資源

    • 比如多個線程訪問同一個對象、同一個變數、同一個文件
  • 當多個線程訪問同一塊資源時,很容易引發數據錯亂和數據安全問題

安全隱患實例 -- 存取錢 && 賣票

同一個賬戶,多線程同時操作

OS X 和iOS 中的多線程技術(上)

OS X 和iOS 中的多線程技術(上)

如圖,多個線程同時操作一個數據,導致 A 線程讀到數據尚未修改完成之前,另一個線程 B 也同時讀到了數據,當 B 要修改的時候,A 已經把原來的數據修改了,B 修改的數據依舊是之前的數據。這樣就導致了多線程操作同一個數據的數據混亂。

安全隱患分析圖示如下

OS X 和iOS 中的多線程技術(上)

安全隱患的解決

解決多線程的安全隱患,就加一個互斥鎖,當一個線程訪問並操作數據的時候,鎖住對應數據,防止其他線程訪問,當該線程訪問數據並操作完,放開互斥鎖,其他線程再進行訪問。

OS X 和iOS 中的多線程技術(上)

  • 互斥鎖使用格式

@synchronized(鎖對象) { // 需要鎖定的代碼 }

注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的

  • 互斥鎖的優缺點

    • 優點:能有效防止因多線程搶奪資源造成的數據安全問題
    • 缺點:需要消耗大量的CPU資源
  • 互斥鎖的使用前提:多條線程搶奪同一塊資源

  • 相關專業術語:線程同步

    線程同步的意思是:多條線程在同一條線上執行(按順序地執行任務)

    互斥鎖,就是使用了線程同步技術

6 原子和非原子屬性

  • OC在定義屬性時有nonatomic和atomic兩種選擇

    • atomic:原子屬性,為setter方法加鎖(默認就是atomic)
    • nonatomic:非原子屬性,不會為setter方法加鎖
  • nonatomic和atomic對比

    • atomic:線程安全,需要消耗大量的資源
    • nonatomic:非線程安全,適合內存小的移動設備

iOS開發的建議

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

7 線程間通信

  • 什麼叫做線程間通信 在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;

  • 線程間通信實例-圖片下載

主線程需要展示圖片,圖片下載比較耗時,就放到子線程去操作。當子線程圖片下載完成後,回到主線程進行圖片賦值並展示。

OS X 和iOS 中的多線程技術(上)

小結

本篇文章主要講解了多線程的一些基礎知識和 pthread 和 NSTread 兩種多線程方案。接下來會在下一篇文章中介紹 GCD 和 NSOpreation 的使用。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

View Components as Tag Helpers,離在線模板編輯又進一步
淺談MVC Form認證
asp.net core中負載均衡場景下http重定向https的問題
原生JS+Canvas實現五子棋遊戲
JAVA String 不可變性

TAG:科技優家 |

您可能感興趣

BTC、ETH、EOS,安全、公平、效率
ADA、ONT、EOS、AE對比及投資策略
18年秀場錦集:TOM FORD,CHANNEL和JOHN VARVATOS
為ZEN+新銳龍而生,信仰級X470主板駕到!華碩ROG CROSSHAIRⅦHERO首發開箱
東芝發布CD5/XD5/HK6-DC系列NVMe SSD與KumoScale軟體
[MD PHOTO]高庚杓趙在鉉等藝人出席tvN新劇 《CROSS》發布會
AM4平台支持Ryzen APU!華碩、技嘉和華擎主板全線更新BIOS
NAB上的羅德、ATOMOS、Wooden Camera
俄勒岡州的希臘女神之三十:外場之王,NIKE ZOOM HYPERCHAOS X
萬柚引力組-漫畫:ETH VS EOS,領略EOS之美
福熙Talk Say PS教程:PHOTOSHOP製作梅花扇面效果
男人的情懷之VOLVO V70 CROSS COUNTRY AWD
英文美文:碩果與玫瑰RESULTS AND ROSES
BOBOSNAP時裝精|探索英國本土設計師品牌(二)
專訪TOS CEO,CTO:一個去中心化、安全可靠、快速透明的數據交換平台
創意髮型:荷蘭 HANS BEERS-INTROSPECTIVE
華麗大變身,KAWASAKI Z900RS 「THE GOOSE」
吳一龍教授再亮劍,EGFR、ALK、ROS1基因聯合檢測新時代
JOSHUA SANDERS 為全新鞋款 ZENITH 打造 Lookbook
快傳開箱 AIR FOAMPOSITE PRO AS QS